home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
- #include "qcc.h"
-
- /*=========================================================================== */
-
- char sourcedir[NAMELEN_PATH]; /* 256 */
- char destfile[NAMELEN_PATH]; /* 256 */
-
- float *pr_globals = 0; /*[MAX_REGS]; // 65536 */
- int numpr_globals; /* 4 */
-
- char *strings = 0; /*[MAX_STRINGS]; // 500000 */
- int strofs; /* 4 */
-
- dstatement_t *statements = 0; /*[MAX_STATEMENTS]; // 65536 * 8 = 524288 */
- int numstatements; /* 4 */
- int *statement_linenums = 0; /*[MAX_STATEMENTS]; // 65536 * 4 = 262144 */
-
- dfunction_t *functions = 0; /*[MAX_FUNCTIONS]; // 8192 * (28 + 8) = 294912 */
- int numfunctions; /* 4 */
-
- ddef_t *globals = 0; /*[MAX_GLOBALS]; // 16384 * 10 = 163840 */
- int numglobaldefs; /* 4 */
-
- ddef_t *fields = 0; /*[MAX_FIELDS]; // 1024 * 10 = 10240 */
- int numfielddefs; /* 4 */
-
- char precache_sounds[MAX_SOUNDS][MAX_DATA_PATH]; /* 1024 * 64 = 65536 */
- int precache_sounds_block[MAX_SOUNDS]; /* 1024 * 4 = 4096 */
- int numsounds; /* 4 */
-
- char precache_models[MAX_MODELS][MAX_DATA_PATH]; /* 1024 * 64 = 65536 */
- int precache_models_block[MAX_SOUNDS]; /* 1024 * 4 = 4096 */
- int nummodels; /* 4 */
-
- char precache_files[MAX_FILES][MAX_DATA_PATH]; /* 1024 * 64 = 65536 */
- int precache_files_block[MAX_SOUNDS]; /* 1024 * 4 = 4096 */
- int numfiles; /* 4 */
-
- /*=========================================================================== */
-
- int pr_source_line;
-
- char *pr_file_p;
-
- /* start of current source line */
- char *pr_line_start;
-
- int pr_bracelevel;
-
- char pr_token[2048];
- token_type_t pr_token_type;
- type_t *pr_immediate_type;
- eval_t pr_immediate;
-
- char pr_immediate_string[2048];
-
- int pr_error_count;
-
- char *pr_punctuation[] =
- /* longer symbols must be before a shorter partial match */
- {"&&", "||", "<=", ">=", "==", "!=", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", ".", "<", ">", "#", "&", "|", NULL};
-
- extern def_t def_void;
- extern def_t def_string;
- extern def_t def_float;
- extern def_t def_vector;
- extern def_t def_entity;
- extern def_t def_field;
- extern def_t def_function;
- extern def_t def_pointer;
-
- /* simple types. function types are dynamically allocated */
- type_t type_void =
- {ev_void, &def_void};
- type_t type_string =
- {ev_string, &def_string};
- type_t type_float =
- {ev_float, &def_float};
- type_t type_vector =
- {ev_vector, &def_vector};
- type_t type_entity =
- {ev_entity, &def_entity};
- type_t type_field =
- {ev_field, &def_field};
- type_t type_function =
- {ev_function, &def_function, NULL, &type_void};
-
- /* type_function is a void() function used for state defs */
- type_t type_pointer =
- {ev_pointer, &def_pointer};
-
- type_t type_floatfield =
- {ev_field, &def_field, NULL, &type_float};
-
- int type_size[8] =
- {1, 1, 1, 3, 1, 1, 1, 1};
-
- def_t def_void =
- {&type_void, "temp"};
- def_t def_string =
- {&type_string, "temp"};
- def_t def_float =
- {&type_float, "temp"};
- def_t def_vector =
- {&type_vector, "temp"};
- def_t def_entity =
- {&type_entity, "temp"};
- def_t def_field =
- {&type_field, "temp"};
- def_t def_function =
- {&type_function, "temp"};
- def_t def_pointer =
- {&type_pointer, "temp"};
-
- def_t def_ret, def_parms[MAX_PARMS];
-
- def_t *def_for_type[8] =
- {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer};
-
- /*=========================================================================== */
-
- pr_info_t pr;
- def_t *pr_global_defs[MAX_REGS];
-
- /* to find def for a global variable */
-
- int pr_edict_size;
-
- char pr_parm_names[MAX_PARMS][MAX_NAME];
-
- /*======================================== */
-
- /* the function being parsed, or NULL */
- def_t *pr_scope;
-
- bool pr_dumpasm;
-
- /* filename for function definition */
- string_t s_file;
-
- /* for tracking local variables vs temps */
- int locals_end;
-
- /* longjump with this on parse error */
- jmp_buf pr_parse_abort;
-
- char pr_framemacros[MAX_FRAMES][16];
- int pr_nummacros;
-
- /*======================================== */
-
- opcode_t pr_opcodes[] =
- {
- {"<DONE>", "DONE", -1, FALSE, &def_entity, &def_field, &def_void},
-
- {"*", "MUL_F", 2, FALSE, &def_float, &def_float, &def_float},
- {"*", "MUL_V", 2, FALSE, &def_vector, &def_vector, &def_float},
- {"*", "MUL_FV", 2, FALSE, &def_float, &def_vector, &def_vector},
- {"*", "MUL_VF", 2, FALSE, &def_vector, &def_float, &def_vector},
-
- {"/", "DIV", 2, FALSE, &def_float, &def_float, &def_float},
-
- {"+", "ADD_F", 3, FALSE, &def_float, &def_float, &def_float},
- {"+", "ADD_V", 3, FALSE, &def_vector, &def_vector, &def_vector},
-
- {"-", "SUB_F", 3, FALSE, &def_float, &def_float, &def_float},
- {"-", "SUB_V", 3, FALSE, &def_vector, &def_vector, &def_vector},
-
- {"==", "EQ_F", 4, FALSE, &def_float, &def_float, &def_float},
- {"==", "EQ_V", 4, FALSE, &def_vector, &def_vector, &def_float},
- {"==", "EQ_S", 4, FALSE, &def_string, &def_string, &def_float},
- {"==", "EQ_E", 4, FALSE, &def_entity, &def_entity, &def_float},
- {"==", "EQ_FNC", 4, FALSE, &def_function, &def_function, &def_float},
-
- {"!=", "NE_F", 4, FALSE, &def_float, &def_float, &def_float},
- {"!=", "NE_V", 4, FALSE, &def_vector, &def_vector, &def_float},
- {"!=", "NE_S", 4, FALSE, &def_string, &def_string, &def_float},
- {"!=", "NE_E", 4, FALSE, &def_entity, &def_entity, &def_float},
- {"!=", "NE_FNC", 4, FALSE, &def_function, &def_function, &def_float},
-
- {"<=", "LE", 4, FALSE, &def_float, &def_float, &def_float},
- {">=", "GE", 4, FALSE, &def_float, &def_float, &def_float},
- {"<", "LT", 4, FALSE, &def_float, &def_float, &def_float},
- {">", "GT", 4, FALSE, &def_float, &def_float, &def_float},
-
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_float},
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_vector},
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_string},
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_entity},
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_field},
- {".", "INDIRECT", 1, FALSE, &def_entity, &def_field, &def_function},
-
- {".", "ADDRESS", 1, FALSE, &def_entity, &def_field, &def_pointer},
-
- {"=", "STORE_F", 5, TRUE, &def_float, &def_float, &def_float},
- {"=", "STORE_V", 5, TRUE, &def_vector, &def_vector, &def_vector},
- {"=", "STORE_S", 5, TRUE, &def_string, &def_string, &def_string},
- {"=", "STORE_ENT", 5, TRUE, &def_entity, &def_entity, &def_entity},
- {"=", "STORE_FLD", 5, TRUE, &def_field, &def_field, &def_field},
- {"=", "STORE_FNC", 5, TRUE, &def_function, &def_function, &def_function},
-
- {"=", "STOREP_F", 5, TRUE, &def_pointer, &def_float, &def_float},
- {"=", "STOREP_V", 5, TRUE, &def_pointer, &def_vector, &def_vector},
- {"=", "STOREP_S", 5, TRUE, &def_pointer, &def_string, &def_string},
- {"=", "STOREP_ENT", 5, TRUE, &def_pointer, &def_entity, &def_entity},
- {"=", "STOREP_FLD", 5, TRUE, &def_pointer, &def_field, &def_field},
- {"=", "STOREP_FNC", 5, TRUE, &def_pointer, &def_function, &def_function},
-
- {"<RETURN>", "RETURN", -1, FALSE, &def_void, &def_void, &def_void},
-
- {"!", "NOT_F", -1, FALSE, &def_float, &def_void, &def_float},
- {"!", "NOT_V", -1, FALSE, &def_vector, &def_void, &def_float},
- {"!", "NOT_S", -1, FALSE, &def_vector, &def_void, &def_float},
- {"!", "NOT_ENT", -1, FALSE, &def_entity, &def_void, &def_float},
- {"!", "NOT_FNC", -1, FALSE, &def_function, &def_void, &def_float},
-
- {"<IF>", "IF", -1, FALSE, &def_float, &def_float, &def_void},
- {"<IFNOT>", "IFNOT", -1, FALSE, &def_float, &def_float, &def_void},
-
- /* calls returns REG_RETURN */
- {"<CALL0>", "CALL0", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL1>", "CALL1", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL2>", "CALL2", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL3>", "CALL3", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL4>", "CALL4", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL5>", "CALL5", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL6>", "CALL6", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL7>", "CALL7", -1, FALSE, &def_function, &def_void, &def_void},
- {"<CALL8>", "CALL8", -1, FALSE, &def_function, &def_void, &def_void},
-
- {"<STATE>", "STATE", -1, FALSE, &def_float, &def_float, &def_void},
-
- {"<GOTO>", "GOTO", -1, FALSE, &def_float, &def_void, &def_void},
-
- {"&&", "AND", 6, FALSE, &def_float, &def_float, &def_float},
- {"||", "OR", 6, FALSE, &def_float, &def_float, &def_float},
-
- {"&", "BITAND", 2, FALSE, &def_float, &def_float, &def_float},
- {"|", "BITOR", 2, FALSE, &def_float, &def_float, &def_float},
-
- {NULL}
- };
-
- def_t *PR_Expression(register int priority);
-
- def_t junkdef;
-
- /*
- * ===========================================================================
- * qcc
- * ===========================================================================
- */
-
- /* CopyString returns an offset from the string heap */
- int CopyString(register char *str)
- {
- int old;
-
- old = strofs;
- __strcpy(strings + strofs, str);
- strofs += __strlen(str) + 1;
- return old;
- }
-
- void PrintStrings(void)
- {
- int i, l, j;
-
- for (i = 0; i < strofs; i += l) {
- l = __strlen(strings + i) + 1;
- mprintf("%5i : ", i);
- for (j = 0; j < l; j++) {
- if (strings[i + j] == '\n') {
- putchar('\\');
- putchar('n');
- }
- else
- putchar(strings[i + j]);
- }
- mprintf("\n");
- }
- }
-
- void PrintFunctions(void)
- {
- int i, j;
- dfunction_t *d;
-
- for (i = 0; i < numfunctions; i++) {
- d = &functions[i];
- mprintf("%s : %s : %i %i (", strings + d->s_file, strings + d->s_name, d->first_statement, d->parm_start);
- for (j = 0; j < d->numparms; j++)
- mprintf("%i ", d->parm_size[j]);
- mprintf(")\n");
- }
- }
-
- void PrintFields(void)
- {
- int i;
- ddef_t *d;
-
- for (i = 0; i < numfielddefs; i++) {
- d = &fields[i];
- mprintf("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
- }
- }
-
- void PrintGlobals(void)
- {
- int i;
- ddef_t *d;
-
- for (i = 0; i < numglobaldefs; i++) {
- d = &globals[i];
- mprintf("%5i : (%i) %s\n", d->ofs, d->type, strings + d->s_name);
- }
- }
-
- /*=========================================================================== */
-
- void PrecacheSound(register def_t * e, register int ch)
- {
- char *n;
- int i;
-
- if (!e->ofs)
- return;
- n = G_STRING(e->ofs);
- for (i = 0; i < numsounds; i++)
- if (!__strcmp(n, precache_sounds[i]))
- return;
- if (numsounds == MAX_SOUNDS)
- eprintf("PrecacheSound: numsounds == MAX_SOUNDS");
- __strcpy(precache_sounds[i], n);
- if (ch >= '1' && ch <= '9')
- precache_sounds_block[i] = ch - '0';
- else
- precache_sounds_block[i] = 1;
- numsounds++;
- }
-
- void PrecacheModel(register def_t * e, register int ch)
- {
- char *n;
- int i;
-
- if (!e->ofs)
- return;
- n = G_STRING(e->ofs);
- for (i = 0; i < nummodels; i++)
- if (!__strcmp(n, precache_models[i]))
- return;
- if (numsounds == MAX_SOUNDS)
- eprintf("PrecacheModels: numsounds == MAX_SOUNDS");
- __strcpy(precache_models[i], n);
- if (ch >= '1' && ch <= '9')
- precache_models_block[i] = ch - '0';
- else
- precache_models_block[i] = 1;
- nummodels++;
- }
-
- void PrecacheFile(register def_t * e, register int ch)
- {
- char *n;
- int i;
-
- if (!e->ofs)
- return;
- n = G_STRING(e->ofs);
- for (i = 0; i < numfiles; i++)
- if (!__strcmp(n, precache_files[i]))
- return;
- if (numfiles == MAX_FILES)
- eprintf("PrecacheFile: numfiles == MAX_FILES");
- __strcpy(precache_files[i], n);
- if (ch >= '1' && ch <= '9')
- precache_files_block[i] = ch - '0';
- else
- precache_files_block[i] = 1;
- numfiles++;
- }
-
- /*=========================================================================== */
-
- bool ExitData(void)
- {
- kfree();
-
- return FALSE;
- }
-
- bool InitData(void)
- {
- int i;
-
- if (!(pr_globals = (float *)kmalloc(MAX_REGS * sizeof(float))))
- return ExitData();
- if (!(strings = (char *)kmalloc(MAX_STRINGS * sizeof(char))))
- return ExitData();
-
- if (!(statements = (dstatement_t *) kmalloc(MAX_STATEMENTS * sizeof(dstatement_t))))
- return ExitData();
- if (!(statement_linenums = (int *)kmalloc(MAX_STATEMENTS * sizeof(int))))
- return ExitData();
-
- if (!(functions = (dfunction_t *) kmalloc(MAX_FUNCTIONS * sizeof(dfunction_t))))
- return ExitData();
- if (!(globals = (ddef_t *) kmalloc(MAX_GLOBALS * sizeof(ddef_t))))
- return ExitData();
- if (!(fields = (ddef_t *) kmalloc(MAX_FIELDS * sizeof(ddef_t))))
- return ExitData();
-
- numstatements = 1;
- strofs = 1;
- numfunctions = 1;
- numglobaldefs = 1;
- numfielddefs = 1;
-
- def_ret.ofs = OFS_RETURN;
- for (i = 0; i < MAX_PARMS; i++)
- def_parms[i].ofs = OFS_PARM0 + 3 * i;
-
- return TRUE;
- }
-
- void WriteData(register int crc)
- {
- def_t *def;
- ddef_t *dd;
- dprograms_t progs;
- HANDLE h;
- int i;
-
- for (def = pr.def_head; def; def = def->next) {
- if (def->type->type == ev_function) {
- /*
- * df = &functions[numfunctions];
- * numfunctions++;
- */
- }
- else if (def->type->type == ev_field) {
- dd = &fields[numfielddefs];
- numfielddefs++;
- dd->type = def->type->aux_type->type;
- dd->s_name = CopyString(def->name);
- dd->ofs = G_INT(def->ofs);
- }
- dd = &globals[numglobaldefs];
- numglobaldefs++;
- dd->type = def->type->type;
- if (!def->initialized
- && def->type->type != ev_function
- && def->type->type != ev_field
- && def->scope == NULL)
- dd->type |= DEF_SAVEGLOBGAL;
- dd->s_name = CopyString(def->name);
- dd->ofs = def->ofs;
- }
-
- /*
- * PrintStrings ();
- * PrintFunctions ();
- * PrintFields ();
- * PrintGlobals ();
- */
- strofs = (strofs + 3) & ~3;
-
- mprintf("%6i strofs\n", strofs);
- mprintf("%6i numstatements\n", numstatements);
- mprintf("%6i numfunctions\n", numfunctions);
- mprintf("%6i numglobaldefs\n", numglobaldefs);
- mprintf("%6i numfielddefs\n", numfielddefs);
- mprintf("%6i numpr_globals\n", numpr_globals);
-
- if ((h = __open(destfile, H_READWRITE_BINARY_OLD)) > 0) {
- __write(h, &progs, sizeof(progs));
-
- progs.ofs_strings = __ltell(h);
- progs.numstrings = strofs;
- __write(h, strings, strofs);
-
- progs.ofs_statements = __ltell(h);
- progs.numstatements = numstatements;
- for (i = 0; i < numstatements; i++) {
- statements[i].op = LittleShort(statements[i].op);
- statements[i].a = LittleShort(statements[i].a);
- statements[i].b = LittleShort(statements[i].b);
- statements[i].c = LittleShort(statements[i].c);
- }
- __write(h, statements, numstatements * sizeof(dstatement_t));
-
- progs.ofs_functions = __ltell(h);
- progs.numfunctions = numfunctions;
- for (i = 0; i < numfunctions; i++) {
- functions[i].first_statement = LittleLong(functions[i].first_statement);
- functions[i].parm_start = LittleLong(functions[i].parm_start);
- functions[i].s_name = LittleLong(functions[i].s_name);
- functions[i].s_file = LittleLong(functions[i].s_file);
- functions[i].numparms = LittleLong(functions[i].numparms);
- functions[i].locals = LittleLong(functions[i].locals);
- }
- __write(h, functions, numfunctions * sizeof(dfunction_t));
-
- progs.ofs_globaldefs = __ltell(h);
- progs.numglobaldefs = numglobaldefs;
- for (i = 0; i < numglobaldefs; i++) {
- globals[i].type = LittleShort(globals[i].type);
- globals[i].ofs = LittleShort(globals[i].ofs);
- globals[i].s_name = LittleLong(globals[i].s_name);
- }
- __write(h, globals, numglobaldefs * sizeof(ddef_t));
-
- progs.ofs_fielddefs = __ltell(h);
- progs.numfielddefs = numfielddefs;
- for (i = 0; i < numfielddefs; i++) {
- fields[i].type = LittleShort(fields[i].type);
- fields[i].ofs = LittleShort(fields[i].ofs);
- fields[i].s_name = LittleLong(fields[i].s_name);
- }
- __write(h, fields, numfielddefs * sizeof(ddef_t));
-
- progs.ofs_globals = __ltell(h);
- progs.numglobals = numpr_globals;
- for (i = 0; i < numpr_globals; i++)
- ((int *)pr_globals)[i] = LittleLong(((int *)pr_globals)[i]);
- __write(h, pr_globals, numpr_globals * 4);
-
- mprintf("%6i TOTAL SIZE\n", (int)__ltell(h));
-
- progs.entityfields = pr.size_fields;
- progs.version = PROG_VERSION;
- progs.crc = crc;
-
- /* unsigned char swap the header and write it out */
- for (i = 0; i < sizeof(progs) / 4; i++)
- ((int *)&progs)[i] = LittleLong(((int *)&progs)[i]);
- __lseek(h, 0, SEEK_SET);
- __write(h, &progs, sizeof(progs));
-
- __close(h);
- }
- }
-
- bool ReadData(register HANDLE srcFile)
- {
- dprograms_t progs;
- int i;
- bool retval = FALSE;
-
- while (1) {
- if (__read(srcFile, &progs, sizeof(progs)) != sizeof(progs))
- break;
-
- __lseek(srcFile, LittleLong(progs.ofs_strings), SEEK_SET);
- strofs = LittleLong(progs.numstrings);
- if (!(strings = (char *)kmalloc(strofs)))
- break;
- if (__read(srcFile, strings, strofs) != strofs)
- break;
-
- __lseek(srcFile, LittleLong(progs.ofs_statements), SEEK_SET);
- numstatements = LittleLong(progs.numstatements);
- if (!(statements = (dstatement_t *) kmalloc(numstatements * sizeof(dstatement_t))))
- break;
- if (!(statement_linenums = (int *)kmalloc(numstatements * sizeof(int))))
- break;
-
- if (__read(srcFile, statements, numstatements * sizeof(dstatement_t)) != (numstatements * sizeof(dstatement_t)))
- break;
- for (i = 0; i < numstatements; i++) {
- statements[i].op = LittleShort(statements[i].op);
- statements[i].a = LittleShort(statements[i].a);
- statements[i].b = LittleShort(statements[i].b);
- statements[i].c = LittleShort(statements[i].c);
- }
-
- __lseek(srcFile, LittleLong(progs.ofs_functions), SEEK_SET);
- numfunctions = LittleLong(progs.numfunctions);
- if (!(functions = (dfunction_t *) kmalloc(numfunctions * sizeof(dfunction_t))))
- break;
- if (__read(srcFile, functions, numfunctions * sizeof(dfunction_t)) != (numfunctions * sizeof(dfunction_t)))
- break;
- for (i = 0; i < numfunctions; i++) {
- functions[i].first_statement = LittleLong(functions[i].first_statement);
- functions[i].parm_start = LittleLong(functions[i].parm_start);
- functions[i].locals = LittleLong(functions[i].locals);
- functions[i].s_name = LittleLong(functions[i].s_name);
- functions[i].s_file = LittleLong(functions[i].s_file);
- functions[i].numparms = LittleLong(functions[i].numparms);
- }
-
- __lseek(srcFile, LittleLong(progs.ofs_globaldefs), SEEK_SET);
- numglobaldefs = LittleLong(progs.numglobaldefs);
- if (!(globals = (ddef_t *) kmalloc(numglobaldefs * sizeof(ddef_t))))
- break;
- if (__read(srcFile, globals, numglobaldefs * sizeof(ddef_t)) != (numglobaldefs * sizeof(ddef_t)))
- break;
- for (i = 0; i < numglobaldefs; i++) {
- globals[i].type = LittleShort(globals[i].type);
- globals[i].ofs = LittleShort(globals[i].ofs);
- globals[i].s_name = LittleLong(globals[i].s_name);
- }
-
- __lseek(srcFile, LittleLong(progs.ofs_fielddefs), SEEK_SET);
- numfielddefs = LittleLong(progs.numfielddefs);
- if (!(fields = (ddef_t *) kmalloc(numfielddefs * sizeof(ddef_t))))
- break;
- if (__read(srcFile, fields, numfielddefs * sizeof(ddef_t)) != (numfielddefs * sizeof(ddef_t)))
- break;
- for (i = 0; i < numfielddefs; i++) {
- fields[i].type = LittleShort(fields[i].type);
- fields[i].ofs = LittleShort(fields[i].ofs);
- fields[i].s_name = LittleLong(fields[i].s_name);
- }
-
- __lseek(srcFile, LittleLong(progs.ofs_globals), SEEK_SET);
- numpr_globals = LittleLong(progs.numglobals);
- if (!(pr_globals = (float *)kmalloc(numpr_globals * sizeof(float))))
- break;
-
- if (__read(srcFile, pr_globals, numpr_globals * 4) != (numpr_globals * 4))
- break;
- for (i = 0; i < numpr_globals; i++)
- ((int *)pr_globals)[i] = LittleLong(((int *)pr_globals)[i]);
-
- printf("total size is %6i\n", (int)__ltell(srcFile));
- printf("version code is %i\n", LittleLong(progs.version));
- printf("crc is %i\n", LittleLong(progs.crc));
- printf("%6i strofs\n", strofs);
- printf("%6i numstatements\n", numstatements);
- printf("%6i numfunctions\n", numfunctions);
- printf("%6i numglobaldefs\n", numglobaldefs);
- printf("%6i numfielddefs\n", numfielddefs);
- printf("%6i numpr_globals\n", numpr_globals);
- printf("--------------------------\n");
- retval = TRUE;
- break;
- }
-
- return retval;
- }
-
- bool ShowData(register HANDLE srcFile)
- {
- dprograms_t progs;
-
- if (__read(srcFile, &progs, sizeof(progs)) == sizeof(progs)) {
- strofs = LittleLong(progs.numstrings);
- numstatements = LittleLong(progs.numstatements);
- numfunctions = LittleLong(progs.numfunctions);
- numglobaldefs = LittleLong(progs.numglobaldefs);
- numfielddefs = LittleLong(progs.numfielddefs);
- numpr_globals = LittleLong(progs.numglobals);
-
- __lseek(srcFile, 0, SEEK_END);
- printf("total size is %6i\n", (int)__ltell(srcFile));
- printf("version code is %i\n", LittleLong(progs.version));
- printf("crc is %i\n", LittleLong(progs.crc));
- printf("%6i strofs\n", strofs);
- printf("%6i numstatements\n", numstatements);
- printf("%6i numfunctions\n", numfunctions);
- printf("%6i numglobaldefs\n", numglobaldefs);
- printf("%6i numfielddefs\n", numfielddefs);
- printf("%6i numpr_globals\n", numpr_globals);
- printf("--------------------------\n");
- return TRUE;
- }
- else
- return FALSE;
- }
-
- /*
- *
- * ============
- * WriteFiles
- *
- * Generates files.dat, which contains all of the
- * data files actually used by the game, to be
- * processed by qfiles.exe
- * ============
- */
- void WriteFiles(void)
- {
- FILE *f;
- int i;
- char filename[NAMELEN_PATH];
-
- sprintf(filename, "%sfiles.dat", sourcedir);
- f = __fopen(filename, "w");
- if (!f)
- eprintf("Couldn't open %s", filename);
- else {
- fprintf(f, "%i\n", numsounds);
- for (i = 0; i < numsounds; i++)
- fprintf(f, "%i %s\n", precache_sounds_block[i], precache_sounds[i]);
-
- fprintf(f, "%i\n", nummodels);
- for (i = 0; i < nummodels; i++)
- fprintf(f, "%i %s\n", precache_models_block[i], precache_models[i]);
-
- fprintf(f, "%i\n", numfiles);
- for (i = 0; i < numfiles; i++)
- fprintf(f, "%i %s\n", precache_files_block[i], precache_files[i]);
-
- __fclose(f);
- }
- }
-
- /*=========================================================================== */
-
- /*
- * ============
- * PR_ParseError
- *
- * Aborts the current file load
- * ============
- */
- void PR_ParseError(register char *error,...)
- {
- va_list argptr;
- char string[1024];
-
- va_start(argptr, error);
- vsprintf(string, error, argptr);
- va_end(argptr);
-
- mprintf("%s:%i:%s\n", strings + s_file, pr_source_line, string);
-
- longjmp(pr_parse_abort, 1);
- }
-
- /*
- * ==============
- * PR_PrintNextLine
- * ==============
- */
- void PR_PrintNextLine(void)
- {
- char *t;
-
- mprintf("%3i:", pr_source_line);
- for (t = pr_line_start; *t && *t != '\n'; t++)
- mprintf("%c", *t);
- mprintf("\n");
- }
-
- /*
- * ==============
- * PR_NewLine
- *
- * Call at start of file and when *pr_file_p == '\n'
- * ==============
- */
- void PR_NewLine(void)
- {
- bool m;
-
- if (*pr_file_p == '\n') {
- pr_file_p++;
- m = TRUE;
- }
- else
- m = FALSE;
-
- pr_source_line++;
- pr_line_start = pr_file_p;
-
- /*
- * if (pr_dumpasm)
- * PR_PrintNextLine ();
- */
- if (m)
- pr_file_p--;
- }
-
- /*
- * ==============
- * PR_LexString
- *
- * Parses a quoted string
- * ==============
- */
- void PR_LexString(void)
- {
- int c;
- int len;
-
- len = 0;
- pr_file_p++;
- do {
- c = *pr_file_p++;
- if (!c)
- PR_ParseError("EOF inside quote");
- if (c == '\n')
- PR_ParseError("newline inside quote");
- if (c == '\\') { /* escape char */
- c = *pr_file_p++;
- if (!c)
- PR_ParseError("EOF inside quote");
- if (c == 'n')
- c = '\n';
- else if (c == '"')
- c = '"';
- else
- PR_ParseError("Unknown escape char");
- }
- else if (c == '\"') {
- pr_token[len] = 0;
- pr_token_type = tt_immediate;
- pr_immediate_type = &type_string;
- __strcpy(pr_immediate_string, pr_token);
- return;
- }
- pr_token[len] = c;
- len++;
- } while (1);
- }
-
- /*
- * ==============
- * PR_LexNumber
- * ==============
- */
- float PR_LexNumber(void)
- {
- int c;
- int len;
-
- len = 0;
- c = *pr_file_p;
- do {
- pr_token[len] = c;
- len++;
- pr_file_p++;
- c = *pr_file_p;
- } while ((c >= '0' && c <= '9') || c == '.');
- pr_token[len] = 0;
- return atof(pr_token);
- }
-
- /*
- * ==============
- * PR_LexWhitespace
- * ==============
- */
- void PR_LexWhitespace(void)
- {
- int c;
-
- while (1) {
- /* skip whitespace */
- while ((c = *pr_file_p) <= ' ') {
- if (c == '\n')
- PR_NewLine();
- if (c == 0)
- return; /* end of file */
-
- pr_file_p++;
- }
-
- /* skip // comments */
- if (c == '/' && pr_file_p[1] == '/') {
- while (*pr_file_p && *pr_file_p != '\n')
- pr_file_p++;
- PR_NewLine();
- pr_file_p++;
- continue;
- }
-
- /* skip * * comments */
- if (c == '/' && pr_file_p[1] == '*') {
- do {
- pr_file_p++;
- if (pr_file_p[0] == '\n')
- PR_NewLine();
- if (pr_file_p[1] == 0)
- return;
- } while (pr_file_p[-1] != '*' || pr_file_p[0] != '/');
- pr_file_p++;
- continue;
- }
- break; /* a real character has been found */
-
- }
- }
-
- /*
- * ==============
- * PR_LexVector
- *
- * Parses a single quoted vector
- * ==============
- */
- void PR_LexVector(void)
- {
- int i;
-
- pr_file_p++;
- pr_token_type = tt_immediate;
- pr_immediate_type = &type_vector;
- for (i = 0; i < 3; i++) {
- pr_immediate.vector[i] = PR_LexNumber();
- PR_LexWhitespace();
- }
- if (*pr_file_p != '\'')
- PR_ParseError("Bad vector");
- pr_file_p++;
- }
-
- /*
- * ==============
- * PR_LexName
- *
- * Parses an identifier
- * ==============
- */
- void PR_LexName(void)
- {
- int c;
- int len;
-
- len = 0;
- c = *pr_file_p;
- do {
- pr_token[len] = c;
- len++;
- pr_file_p++;
- c = *pr_file_p;
- } while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9'));
- pr_token[len] = 0;
- pr_token_type = tt_name;
- }
-
- /*
- * ==============
- * PR_LexPunctuation
- * ==============
- */
- void PR_LexPunctuation(void)
- {
- int i;
- int len;
- char *p;
-
- pr_token_type = tt_punct;
-
- for (i = 0; (p = pr_punctuation[i]) != NULL; i++) {
- len = __strlen(p);
- if (!__strncmp(p, pr_file_p, len)) {
- __strcpy(pr_token, p);
- if (p[0] == '{')
- pr_bracelevel++;
- else if (p[0] == '}')
- pr_bracelevel--;
- pr_file_p += len;
- return;
- }
- }
-
- PR_ParseError("Unknown punctuation");
- }
-
- void PR_ClearGrabMacros(void)
- {
- pr_nummacros = 0;
- }
-
- void PR_FindMacro(void)
- {
- int i;
-
- for (i = 0; i < pr_nummacros; i++)
- if (!__strcmp(pr_token, pr_framemacros[i])) {
- sprintf(pr_token, "%d", i);
- pr_token_type = tt_immediate;
- pr_immediate_type = &type_float;
- pr_immediate._float = i;
- return;
- }
- PR_ParseError("Unknown frame macro $%s", pr_token);
- }
-
- /* just parses text, returning FALSE if an eol is reached */
- bool PR_SimpleGetToken(void)
- {
- int c;
- int i;
-
- /* skip whitespace */
- while ((c = *pr_file_p) <= ' ') {
- if (c == '\n' || c == 0)
- return FALSE;
- pr_file_p++;
- }
-
- i = 0;
- while ((c = *pr_file_p) > ' ' && c != ',' && c != ';') {
- pr_token[i] = c;
- i++;
- pr_file_p++;
- }
- pr_token[i] = 0;
- return TRUE;
- }
-
- void PR_ParseFrame(void)
- {
- while (PR_SimpleGetToken()) {
- __strcpy(pr_framemacros[pr_nummacros], pr_token);
- pr_nummacros++;
- }
- }
-
- /*
- * ==============
- * PR_Lex
- *
- * Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
- * ==============
- */
- void PR_LexGrab(void);
- void PR_Lex(void)
- {
- int c;
-
- pr_token[0] = 0;
-
- if (!pr_file_p) {
- pr_token_type = tt_eof;
- return;
- }
-
- PR_LexWhitespace();
-
- c = *pr_file_p;
-
- if (!c) {
- pr_token_type = tt_eof;
- return;
- }
-
- /* handle quoted strings as a unit */
- if (c == '\"') {
- PR_LexString();
- return;
- }
-
- /* handle quoted vectors as a unit */
- if (c == '\'') {
- PR_LexVector();
- return;
- }
-
- /* if the first character is a valid identifier, parse until a non-id */
- /* character is reached */
- if ((c >= '0' && c <= '9') || (c == '-' && pr_file_p[1] >= '0' && pr_file_p[1] <= '9')) {
- pr_token_type = tt_immediate;
- pr_immediate_type = &type_float;
- pr_immediate._float = PR_LexNumber();
- return;
- }
-
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
- PR_LexName();
- return;
- }
-
- if (c == '$') {
- PR_LexGrab();
- return;
- }
-
- /* parse symbol strings until a non-symbol is found */
- PR_LexPunctuation();
- }
-
- /*
- * ==============
- * PR_LexGrab
- *
- * Deals with counting sequence numbers and replacing frame macros
- * ==============
- */
- void PR_LexGrab(void)
- {
- pr_file_p++; /* skip the $ */
-
- if (!PR_SimpleGetToken())
- PR_ParseError("hanging $");
-
- /* check for $frame */
- if (!__strcmp(pr_token, "frame")) {
- PR_ParseFrame();
- PR_Lex();
- }
- /* ignore other known $commands */
- else if (!__strcmp(pr_token, "cd")
- || !__strcmp(pr_token, "origin")
- || !__strcmp(pr_token, "base")
- || !__strcmp(pr_token, "flags")
- || !__strcmp(pr_token, "scale")
- || !__strcmp(pr_token, "skin")) { /* skip to end of line */
-
- while (PR_SimpleGetToken());
- PR_Lex();
- }
- /* look for a frame name macro */
- else
- PR_FindMacro();
- }
-
- /*
- * =============
- * PR_Expect
- *
- * Issues an error if the current token isn't equal to string
- * Gets the next token
- * =============
- */
- void PR_Expect(register char *string)
- {
- if (__strcmp(string, pr_token))
- PR_ParseError("expected %s, found %s", string, pr_token);
- PR_Lex();
- }
-
- /*
- * =============
- * PR_Check
- *
- * Returns TRUE and gets the next token if the current token equals string
- * Returns FALSE and does nothing otherwise
- * =============
- */
- bool PR_Check(register char *string)
- {
- if (__strcmp(string, pr_token))
- return FALSE;
-
- PR_Lex();
- return TRUE;
- }
-
- /*
- * ============
- * PR_ParseName
- *
- * Checks to see if the current token is a valid name
- * ============
- */
- char *PR_ParseName(void)
- {
- static char ident[MAX_NAME];
-
- if (pr_token_type != tt_name)
- PR_ParseError("not a name");
- if (__strlen(pr_token) >= MAX_NAME - 1)
- PR_ParseError("name too long");
- __strcpy(ident, pr_token);
- PR_Lex();
-
- return ident;
- }
-
- /*
- * ============
- * PR_FindType
- *
- * Returns a preexisting complex type that matches the parm, or allocates
- * a new one and copies it out.
- * ============
- */
- type_t *PR_FindType(register type_t * type)
- {
- def_t *def;
- type_t *check;
- int i;
-
- for (check = pr.types; check; check = check->next) {
- if (check->type != type->type
- || check->aux_type != type->aux_type
- || check->num_parms != type->num_parms)
- continue;
-
- for (i = 0; i < type->num_parms; i++)
- if (check->parm_types[i] != type->parm_types[i])
- break;
-
- if (i == type->num_parms)
- return check;
- }
-
- /* allocate a new one */
- check = (type_t *) kmalloc(sizeof(*check));
- *check = *type;
- check->next = pr.types;
- pr.types = check;
-
- /* allocate a generic def for the type, so fields can reference it */
- def = (def_t *) kmalloc(sizeof(def_t));
- def->name = "COMPLEX TYPE";
- def->type = check;
- check->def = def;
- return check;
- }
-
- /*
- * ============
- * PR_SkipToSemicolon
- *
- * For error recovery, also pops out of nested braces
- * ============
- */
- void PR_SkipToSemicolon(void)
- {
- do {
- if (!pr_bracelevel && PR_Check(";"))
- return;
- PR_Lex();
- } while (pr_token[0]); /* eof will return a null token */
-
- }
-
- /*
- * ============
- * PR_ParseType
- *
- * Parses a variable type, including field and functions types
- * ============
- */
- type_t *PR_ParseType(void)
- {
- type_t new;
- type_t *type;
- char *name;
-
- if (PR_Check(".")) {
- __bzero(&new, sizeof(new));
- new.type = ev_field;
- new.aux_type = PR_ParseType();
- return PR_FindType(&new);
- }
-
- if (!__strcmp(pr_token, "float"))
- type = &type_float;
- else if (!__strcmp(pr_token, "vector"))
- type = &type_vector;
- else if (!__strcmp(pr_token, "float"))
- type = &type_float;
- else if (!__strcmp(pr_token, "entity"))
- type = &type_entity;
- else if (!__strcmp(pr_token, "string"))
- type = &type_string;
- else if (!__strcmp(pr_token, "void"))
- type = &type_void;
- else {
- PR_ParseError("\"%s\" is not a type", pr_token);
- type = &type_float; /* shut up compiler warning */
- }
- PR_Lex();
-
- if (!PR_Check("("))
- return type;
-
- /* function type */
- __bzero(&new, sizeof(new));
- new.type = ev_function;
- new.aux_type = type; /* return type */
-
- new.num_parms = 0;
- if (!PR_Check(")")) {
- if (PR_Check("..."))
- new.num_parms = -1; /* variable args */
- else
- do {
- type = PR_ParseType();
- name = PR_ParseName();
- __strcpy(pr_parm_names[new.num_parms], name);
- new.parm_types[new.num_parms] = type;
- new.num_parms++;
- } while (PR_Check(","));
-
- PR_Expect(")");
- }
-
- return PR_FindType(&new);
- }
- /*
- * ============
- * PR_Statement
- *
- * Emits a primitive statement, returning the var it places it's value in
- * ============
- */
- def_t *PR_Statement(register opcode_t * op, register def_t * var_a, register def_t * var_b)
- {
- dstatement_t *statement;
- def_t *var_c;
-
- statement = &statements[numstatements];
- numstatements++;
-
- statement_linenums[statement - statements] = pr_source_line;
- statement->op = op - pr_opcodes;
- statement->a = var_a ? var_a->ofs : 0;
- statement->b = var_b ? var_b->ofs : 0;
- if (op->type_c == &def_void || op->right_associative) {
- var_c = NULL;
- statement->c = 0; /* ifs, gotos, and assignments */
- /* don't need vars allocated */
-
- }
- else { /* allocate result space */
-
- var_c = (def_t *) kmalloc(sizeof(def_t));
- /*__bzero(var_c, sizeof(def_t)); */
- var_c->ofs = numpr_globals;
- var_c->type = op->type_c->type;
-
- statement->c = numpr_globals;
- numpr_globals += type_size[op->type_c->type->type];
- }
-
- if (op->right_associative)
- return var_a;
- return var_c;
- }
-
- /*
- * ============
- * PR_ParseImmediate
- *
- * Looks for a preexisting constant
- * ============
- */
- #if 0
- def_t *PR_ParseImmediate(void)
- {
- def_t *cn;
-
- /* check for a constant with the same value */
- for (cn = pr.def_head.next; cn; cn = cn->next) {
- if (!cn->initialized)
- continue;
- if (cn->type != pr_immediate_type)
- continue;
- if (pr_immediate_type == &type_string) {
- if (!__strcmp(G_STRING(cn->ofs), pr_immediate_string)) {
- PR_Lex();
- return cn;
- }
- }
- else if (pr_immediate_type == &type_float) {
- if (G_FLOAT(cn->ofs) == pr_immediate._float) {
- PR_Lex();
- return cn;
- }
- }
- else if (pr_immediate_type == &type_vector) {
- if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0])
- && (G_FLOAT(cn->ofs + 1) == pr_immediate.vector[1])
- && (G_FLOAT(cn->ofs + 2) == pr_immediate.vector[2])) {
- PR_Lex();
- return cn;
- }
- }
- else
- PR_ParseError("weird immediate type");
- }
-
- /* allocate a new one */
- cn = (def_t *) kmalloc(sizeof(def_t));
- cn->next = NULL;
-
- pr.def_tail->next = cn;
-
- pr.def_tail = cn;
-
- cn->search_next = pr.search;
-
- pr.search = cn;
-
- cn->type = pr_immediate_type;
- cn->name = "IMMEDIATE";
- cn->initialized = 1;
- cn->scope = NULL; /* always share immediates */
-
- /* copy the immediate to the global area */
- cn->ofs = numpr_globals;
- pr_global_defs[cn->ofs] = cn;
- numpr_globals += type_size[pr_immediate_type->type];
- if (pr_immediate_type == &type_string)
- pr_immediate.string = CopyString(pr_immediate_string);
-
- memcpy(pr_globals + cn->ofs, &pr_immediate, 4 * type_size[pr_immediate_type->type]);
-
- PR_Lex();
-
- return cn;
- }
- #else
- def_t *PR_ParseImmediate(void)
- {
- #undef cacheSize
- #undef cacheMask
- #define cacheSize 32
- #define cacheMask (cacheSize - 1)
- static def_t *stringCache[cacheSize];
- static int stringTop = 0;
- static def_t *floatCache[cacheSize];
- static int floatTop = 0;
- static def_t *vectorCache[cacheSize];
- static int vectorTop = 0;
- int sub;
- def_t *cn;
-
- if (pr_immediate_type == &type_string) {
- /* See if constant is in cache. */
- sub = stringTop;
- do {
- cn = stringCache[sub];
- if (!cn)
- break;
- if (!__strcmp(G_STRING(cn->ofs), pr_immediate_string)) {
- PR_Lex();
- stringCache[sub] = stringCache[stringTop];
- stringCache[stringTop] = cn;
- return cn;
- }
- sub = (sub - 1) & cacheMask;
- }
- while (sub != stringTop);
-
- /* See if constant is in main list. */
- for (cn = pr.def_tail; cn; cn = cn->prev) {
- if (!cn->initialized || cn->type != pr_immediate_type)
- continue;
- if (!__strcmp(G_STRING(cn->ofs), pr_immediate_string)) {
- PR_Lex();
- stringTop = (stringTop + 1) & cacheMask;
- stringCache[stringTop] = cn;
- return cn;
- }
- }
- }
- else if (pr_immediate_type == &type_float) {
- /* See if constant is in cache. */
- sub = floatTop;
- do {
- cn = floatCache[sub];
- if (!cn)
- break;
- if (G_FLOAT(cn->ofs) == pr_immediate._float) {
- PR_Lex();
- floatCache[sub] = floatCache[floatTop];
- floatCache[floatTop] = cn;
- return cn;
- }
- sub = (sub - 1) & cacheMask;
- }
- while (sub != floatTop);
-
- /* See if constant is in main list. */
- for (cn = pr.def_tail; cn; cn = cn->prev) {
- if (!cn->initialized || cn->type != pr_immediate_type)
- continue;
- if (G_FLOAT(cn->ofs) == pr_immediate._float) {
- PR_Lex();
- floatTop = (floatTop + 1) & cacheMask;
- floatCache[floatTop] = cn;
- return cn;
- }
- }
- }
- else if (pr_immediate_type == &type_vector) {
- /* See if constant is in cache. */
- sub = vectorTop;
- do {
- cn = vectorCache[sub];
- if (!cn)
- break;
- if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0])
- && (G_FLOAT(cn->ofs + 1) == pr_immediate.vector[1])
- && (G_FLOAT(cn->ofs + 2) == pr_immediate.vector[2])) {
- PR_Lex();
- vectorCache[sub] = vectorCache[vectorTop];
- vectorCache[vectorTop] = cn;
- return cn;
- }
- sub = (sub - 1) & cacheMask;
- }
- while (sub != vectorTop);
-
- /* See if constant is in main list. */
- for (cn = pr.def_tail; cn; cn = cn->prev) {
- if (!cn->initialized || cn->type != pr_immediate_type)
- continue;
- if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0])
- && (G_FLOAT(cn->ofs + 1) == pr_immediate.vector[1])
- && (G_FLOAT(cn->ofs + 2) == pr_immediate.vector[2])) {
- PR_Lex();
- vectorTop = (vectorTop + 1) & cacheMask;
- vectorCache[vectorTop] = cn;
- return cn;
- }
- }
- }
- else {
- PR_ParseError("weird immediate type");
- }
-
- /* allocate a new one */
- cn = (def_t *) kmalloc(sizeof(def_t));
- cn->next = NULL;
- if (!pr.def_head) {
- cn->prev = NULL;
- pr.def_head = pr.def_tail = cn;
- }
- else {
- pr.def_tail->next = cn;
- cn->prev = pr.def_tail;
- pr.def_tail = cn;
- }
- cn->type = pr_immediate_type;
- cn->name = "IMMEDIATE";
- cn->initialized = 1;
- cn->scope = NULL; /* always share immediates */
-
- /* Copy the immediate to the global area */
- cn->ofs = numpr_globals;
- pr_global_defs[cn->ofs] = cn;
-
- /* Put immediate into cache. */
- if (pr_immediate_type == &type_string) {
- stringTop = (stringTop + 1) & cacheMask;
- stringCache[stringTop] = cn;
- }
- else if (pr_immediate_type == &type_float) {
- floatTop = (floatTop + 1) & cacheMask;
- floatCache[floatTop] = cn;
- }
- else {
- vectorTop = (vectorTop + 1) & cacheMask;
- vectorCache[vectorTop] = cn;
- }
-
- numpr_globals += type_size[pr_immediate_type->type];
- if (pr_immediate_type == &type_string)
- pr_immediate.string = CopyString(pr_immediate_string);
-
- __memcpy(pr_globals + cn->ofs, &pr_immediate, 4 * type_size[pr_immediate_type->type]);
-
- PR_Lex();
-
- return cn;
- }
- #endif
-
- /*
- * ============
- * PR_ParseFunctionCall
- * ============
- */
- def_t *PR_ParseFunctionCall(register def_t * func)
- {
- def_t *e;
- int arg;
- type_t *t;
-
- t = func->type;
-
- if (t->type != ev_function)
- PR_ParseError("not a function");
-
- /* copy the arguments to the global parameter variables */
- arg = 0;
- if (!PR_Check(")")) {
- do {
- if (t->num_parms != -1 && arg >= t->num_parms)
- PR_ParseError("too many parameters");
- e = PR_Expression(TOP_PRIORITY);
-
- if (arg == 0 && func->name) {
- /* save information for model and sound caching */
- if (!__strncmp(func->name, "precache_sound", 14))
- PrecacheSound(e, func->name[14]);
- else if (!__strncmp(func->name, "precache_model", 14))
- PrecacheModel(e, func->name[14]);
- else if (!__strncmp(func->name, "precache_file", 13))
- PrecacheFile(e, func->name[13]);
- }
-
- if (t->num_parms != -1 && (e->type != t->parm_types[arg]))
- PR_ParseError("type mismatch on parm %i", arg);
- /* a vector copy will copy everything */
- def_parms[arg].type = t->parm_types[arg];
- PR_Statement(&pr_opcodes[OP_STORE_V], e, &def_parms[arg]);
- arg++;
- } while (PR_Check(","));
-
- if (t->num_parms != -1 && arg != t->num_parms)
- PR_ParseError("too few parameters");
- PR_Expect(")");
- }
- if (arg > 8)
- PR_ParseError("More than eight parameters");
-
- PR_Statement(&pr_opcodes[OP_CALL0 + arg], func, 0);
-
- def_ret.type = t->aux_type;
- return &def_ret;
- }
-
- /*
- * ============
- * PR_GetDef
- *
- * If type is NULL, it will match any type
- * If allocate is TRUE, a new def will be allocated if it can't be found
- * ============
- */
- #if 0
- def_t *PR_GetDef(register type_t * type, register char *name, register def_t * scope, register bool allocate)
- {
- def_t *def, **old;
- char element[MAX_NAME];
-
- /* see if the name is already in use */
- old = &pr.search;
- for (def = *old; def; old = &def->search_next, def = *old)
- if (!__strcmp(def->name, name)) {
- if (def->scope && def->scope != scope)
- continue; /* in a different function */
-
- if (type && def->type != type)
- PR_ParseError("Type mismatch on redeclaration of %s", name);
-
- /* move to head of list to find fast next time */
- *old = def->search_next;
-
- def->search_next = pr.search;
-
- pr.search = def;
-
- return def;
- }
-
- if (!allocate)
- return NULL;
-
- /* allocate a new def */
- def = (def_t *) kmalloc(sizeof(def_t));
- /*bzero(def, sizeof(*def)); */
- def->next = NULL;
- pr.def_tail->next = def;
-
- pr.def_tail = def;
-
- def->search_next = pr.search;
-
- pr.search = def;
-
- /*def->name = (char *)kmalloc(__strlen(name) + 1); */
- /*__strcpy(def->name, name); */
- def->name = smalloc(name);
- def->type = type;
-
- def->scope = scope;
-
- def->ofs = numpr_globals;
- pr_global_defs[numpr_globals] = def;
-
- /*
- * make automatic defs for the vectors elements
- * .origin can be accessed as .origin_x, .origin_y, and .origin_z
- */
- if (type->type == ev_vector) {
- sprintf(element, "%s_x", name);
- PR_GetDef(&type_float, element, scope, TRUE);
-
- sprintf(element, "%s_y", name);
- PR_GetDef(&type_float, element, scope, TRUE);
-
- sprintf(element, "%s_z", name);
- PR_GetDef(&type_float, element, scope, TRUE);
- }
- else
- numpr_globals += type_size[type->type];
-
- if (type->type == ev_field) {
- *(int *)&pr_globals[def->ofs] = pr.size_fields;
-
- if (type->aux_type->type == ev_vector) {
- sprintf(element, "%s_x", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
-
- sprintf(element, "%s_y", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
-
- sprintf(element, "%s_z", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
- }
- else
- pr.size_fields += type_size[type->aux_type->type];
- }
-
- /* if (pr_dumpasm) */
- /* PR_PrintOfs (def->ofs); */
-
- return def;
- }
- #else
- def_t *PR_GetDef(register type_t * type, register char *name, register def_t * scope, register bool allocate)
- {
- #undef cacheSize
- #undef cacheMask
- #define cacheSize 128
- #define cacheMask (cacheSize - 1)
- static def_t *cache[cacheSize];
- static int top = 0;
- def_t *def;
- int len;
- char element[MAX_NAME];
-
- /* See if name is in cache. */
- int sub = top;
-
- do {
- def = cache[sub];
- if (!def)
- break;
- if (!def->scope || def->scope == scope) {
- if (!__strcmp(def->name, name)) {
- if (type && def->type != type)
- PR_ParseError(
- "Type mismatch on redeclaration of %s", name);
- cache[sub] = cache[top];
- cache[top] = def;
- return def;
- }
- }
- sub = (sub - 1) & cacheMask;
- }
- while (sub != top);
-
- /* See if name is in main list. */
- for (def = pr.def_tail; def; def = def->prev) {
- if (!def->scope || def->scope == scope) {
- if (!__strcmp(def->name, name)) {
- if (type && def->type != type)
- PR_ParseError(
- "Type mismatch on redeclaration of %s", name);
-
- /* Put entry in cache. */
- top = (top + 1) & cacheMask;
- cache[top] = def;
- return def;
- }
- }
- }
-
- if (!allocate)
- return NULL;
-
- /* allocate a new def */
- len = __strlen(name) + 1;
- def = malloc(sizeof(def_t) + len);
- def->next = NULL;
- if (!pr.def_head) {
- def->prev = NULL;
- pr.def_head = pr.def_tail = def;
- }
- else {
- pr.def_tail->next = def;
- def->prev = pr.def_tail;
- pr.def_tail = def;
- }
- def->name = (char *)def + sizeof(def_t);
- memcpy(def->name, name, len);
- def->type = type;
- def->initialized = 0;
- def->scope = scope;
- def->ofs = numpr_globals;
- pr_global_defs[numpr_globals] = def;
-
- /* Put entry in cache. */
- top = (top + 1) & cacheMask;
- cache[top] = def;
-
- /*
- * make automatic defs for the vectors elements
- * .origin can be accessed as .origin_x, .origin_y, and .origin_z
- */
- if (type->type == ev_vector) {
- sprintf(element, "%s_x", name);
- PR_GetDef(&type_float, element, scope, TRUE);
-
- sprintf(element, "%s_y", name);
- PR_GetDef(&type_float, element, scope, TRUE);
-
- sprintf(element, "%s_z", name);
- PR_GetDef(&type_float, element, scope, TRUE);
- }
- else
- numpr_globals += type_size[type->type];
-
- if (type->type == ev_field) {
- *(int *)&pr_globals[def->ofs] = pr.size_fields;
-
- if (type->aux_type->type == ev_vector) {
- sprintf(element, "%s_x", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
-
- sprintf(element, "%s_y", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
-
- sprintf(element, "%s_z", name);
- PR_GetDef(&type_floatfield, element, scope, TRUE);
- }
- else
- pr.size_fields += type_size[type->aux_type->type];
- }
-
- /* if (pr_dumpasm) */
- /* PR_PrintOfs (def->ofs); */
-
- return def;
- }
- #endif
-
- /*
- * ============
- * PR_ParseValue
- *
- * Returns the global ofs for the current token
- * ============
- */
- def_t *PR_ParseValue(void)
- {
- def_t *d;
- char *name;
-
- /* if the token is an immediate, allocate a constant for it */
- if (pr_token_type == tt_immediate)
- return PR_ParseImmediate();
-
- name = PR_ParseName();
-
- /* look through the defs */
- d = PR_GetDef(NULL, name, pr_scope, FALSE);
- if (!d)
- PR_ParseError("Unknown value \"%s\"", name);
- return d;
- }
-
- /*
- * ============
- * PR_Term
- * ============
- */
- def_t *PR_Term(void)
- {
- def_t *e, *e2;
- etype_t t;
-
- if (PR_Check("!")) {
- e = PR_Expression(NOT_PRIORITY);
- t = e->type->type;
- if (t == ev_float)
- e2 = PR_Statement(&pr_opcodes[OP_NOT_F], e, 0);
- else if (t == ev_string)
- e2 = PR_Statement(&pr_opcodes[OP_NOT_S], e, 0);
- else if (t == ev_entity)
- e2 = PR_Statement(&pr_opcodes[OP_NOT_ENT], e, 0);
- else if (t == ev_vector)
- e2 = PR_Statement(&pr_opcodes[OP_NOT_V], e, 0);
- else if (t == ev_function)
- e2 = PR_Statement(&pr_opcodes[OP_NOT_FNC], e, 0);
- else {
- e2 = NULL; /* shut up compiler warning; */
-
- PR_ParseError("type mismatch for !");
- }
- return e2;
- }
-
- if (PR_Check("(")) {
- e = PR_Expression(TOP_PRIORITY);
- PR_Expect(")");
- return e;
- }
-
- return PR_ParseValue();
- }
-
- /*
- * ==============
- * PR_Expression
- * ==============
- */
-
- def_t *PR_Expression(register int priority)
- {
- opcode_t *op, *oldop;
- def_t *e, *e2;
- etype_t type_a, type_b, type_c;
-
- if (priority == 0)
- return PR_Term();
-
- e = PR_Expression(priority - 1);
-
- while (1) {
- if (priority == 1 && PR_Check("("))
- return PR_ParseFunctionCall(e);
-
- for (op = pr_opcodes; op->name; op++) {
- if (op->priority != priority)
- continue;
- if (!PR_Check(op->name))
- continue;
- if (op->right_associative) {
- /* if last statement is an indirect, change it to an address of */
- if ((unsigned)(statements[numstatements - 1].op - OP_LOAD_F) < 6) {
- statements[numstatements - 1].op = OP_ADDRESS;
- def_pointer.type->aux_type = e->type;
- e->type = def_pointer.type;
- }
- e2 = PR_Expression(priority);
- }
- else
- e2 = PR_Expression(priority - 1);
-
- /* type check */
- type_a = e->type->type;
- type_b = e2->type->type;
-
- if (op->name[0] == '.') { /* field access gets type from field */
- if (e2->type->aux_type)
- type_c = e2->type->aux_type->type;
- else
- type_c = -1; /* not a field */
-
- }
- else
- type_c = ev_void;
-
- oldop = op;
- while (type_a != op->type_a->type->type
- || type_b != op->type_b->type->type
- || (type_c != ev_void && type_c != op->type_c->type->type)) {
- op++;
- if (!op->name || __strcmp(op->name, oldop->name))
- PR_ParseError("type mismatch for %s", oldop->name);
- }
-
- if (type_a == ev_pointer && type_b != e->type->aux_type->type)
- PR_ParseError("type mismatch for %s", op->name);
-
- if (op->right_associative)
- e = PR_Statement(op, e2, e);
- else
- e = PR_Statement(op, e, e2);
-
- if (type_c != ev_void) /* field access gets type from field */
- e->type = e2->type->aux_type;
-
- break;
- }
- if (!op->name)
- break; /* next token isn't at this priority level */
-
- }
-
- return e;
- }
-
- /*
- * ============
- * PR_ParseStatement
- *
- * ============
- */
- void PR_ParseDefs(void);
- void PR_ParseStatement(void)
- {
- def_t *e;
- dstatement_t *patch1, *patch2;
-
- if (PR_Check("{")) {
- do {
- PR_ParseStatement();
- } while (!PR_Check("}"));
- return;
- }
-
- if (PR_Check("return")) {
- if (PR_Check(";")) {
- PR_Statement(&pr_opcodes[OP_RETURN], 0, 0);
- return;
- }
- e = PR_Expression(TOP_PRIORITY);
- PR_Expect(";");
- PR_Statement(&pr_opcodes[OP_RETURN], e, 0);
- return;
- }
-
- if (PR_Check("while")) {
- PR_Expect("(");
- patch2 = &statements[numstatements];
- e = PR_Expression(TOP_PRIORITY);
- PR_Expect(")");
- patch1 = &statements[numstatements];
- PR_Statement(&pr_opcodes[OP_IFNOT], e, 0);
- PR_ParseStatement();
- junkdef.ofs = patch2 - &statements[numstatements];
- PR_Statement(&pr_opcodes[OP_GOTO], &junkdef, 0);
- patch1->b = &statements[numstatements] - patch1;
- return;
- }
-
- if (PR_Check("do")) {
- patch1 = &statements[numstatements];
- PR_ParseStatement();
- PR_Expect("while");
- PR_Expect("(");
- e = PR_Expression(TOP_PRIORITY);
- PR_Expect(")");
- PR_Expect(";");
- junkdef.ofs = patch1 - &statements[numstatements];
- PR_Statement(&pr_opcodes[OP_IF], e, &junkdef);
- return;
- }
-
- if (PR_Check("local")) {
- PR_ParseDefs();
- locals_end = numpr_globals;
- return;
- }
-
- if (PR_Check("if")) {
- PR_Expect("(");
- e = PR_Expression(TOP_PRIORITY);
- PR_Expect(")");
-
- patch1 = &statements[numstatements];
- PR_Statement(&pr_opcodes[OP_IFNOT], e, 0);
-
- PR_ParseStatement();
-
- if (PR_Check("else")) {
- patch2 = &statements[numstatements];
- PR_Statement(&pr_opcodes[OP_GOTO], 0, 0);
- patch1->b = &statements[numstatements] - patch1;
- PR_ParseStatement();
- patch2->a = &statements[numstatements] - patch2;
- }
- else
- patch1->b = &statements[numstatements] - patch1;
-
- return;
- }
-
- PR_Expression(TOP_PRIORITY);
- PR_Expect(";");
- }
-
- /*
- * ==============
- * PR_ParseState
- *
- * States are special functions made for convenience. They automatically
- * set frame, nextthink (implicitly), and think (allowing forward definitions).
- *
- * // void() name = [framenum, nextthink] {code}
- * // expands to:
- * // function void name ()
- * // {
- * // self.frame=framenum;
- * // self.nextthink = time + 0.1;
- * // self.think = nextthink
- * // <code>
- * // };
- * ==============
- */
- void PR_ParseState(void)
- {
- char *name;
- def_t *s1, *def;
-
- if (pr_token_type != tt_immediate || pr_immediate_type != &type_float)
- PR_ParseError("state frame must be a number");
- s1 = PR_ParseImmediate();
-
- PR_Expect(",");
-
- name = PR_ParseName();
- def = PR_GetDef(&type_function, name, 0, TRUE);
-
- PR_Expect("]");
-
- PR_Statement(&pr_opcodes[OP_STATE], s1, def);
- }
-
- /*
- * ============
- * PR_ParseImmediateStatements
- *
- * Parse a function body
- * ============
- */
- function_t *PR_ParseImmediateStatements(register type_t * type)
- {
- int i;
- function_t *f;
- def_t *defs[MAX_PARMS];
-
- f = (function_t *) kmalloc(sizeof(function_t));
-
- /*
- * check for builtin function definition #1, #2, etc
- */
- if (PR_Check("#")) {
- if (pr_token_type != tt_immediate
- || pr_immediate_type != &type_float
- || pr_immediate._float != (int)pr_immediate._float)
- PR_ParseError("Bad builtin immediate");
- f->builtin = (int)pr_immediate._float;
- PR_Lex();
- return f;
- }
-
- f->builtin = 0;
- /*
- * define the parms
- */
- for (i = 0; i < type->num_parms; i++) {
- defs[i] = PR_GetDef(type->parm_types[i], pr_parm_names[i], pr_scope, TRUE);
- f->parm_ofs[i] = defs[i]->ofs;
- if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i - 1])
- PR_ParseError("bad parm order");
- }
-
- f->code = numstatements;
-
- /*
- * check for a state opcode
- */
- if (PR_Check("["))
- PR_ParseState();
-
- /*
- * parse regular statements
- */
- PR_Expect("{");
-
- while (!PR_Check("}"))
- PR_ParseStatement();
-
- /* emit an end of statements opcode */
- PR_Statement(pr_opcodes, 0, 0);
-
- return f;
- }
-
- /*
- * ================
- * PR_ParseDefs
- *
- * Called at the outer layer and when a local statement is hit
- * ================
- */
- void PR_ParseDefs(void)
- {
- char *name;
- type_t *type;
- def_t *def;
- function_t *f;
- dfunction_t *df;
- int i;
- int locals_start;
-
- type = PR_ParseType();
-
- if (pr_scope && (type->type == ev_field || type->type == ev_function))
- PR_ParseError("Fields and functions must be global");
-
- do {
- name = PR_ParseName();
-
- def = PR_GetDef(type, name, pr_scope, TRUE);
-
- /* check for an initialization */
- if (PR_Check("=")) {
- if (def->initialized)
- PR_ParseError("%s redeclared", name);
-
- if (type->type == ev_function) {
- locals_start = locals_end = numpr_globals;
- pr_scope = def;
- f = PR_ParseImmediateStatements(type);
- pr_scope = NULL;
- def->initialized = 1;
- G_FUNCTION(def->ofs) = numfunctions;
- f->def = def;
- /* if (pr_dumpasm) */
- /* PR_PrintFunction (def); */
-
- /* fill in the dfunction */
- df = &functions[numfunctions];
- numfunctions++;
- if (f->builtin)
- df->first_statement = -f->builtin;
- else
- df->first_statement = f->code;
- df->s_name = CopyString(f->def->name);
- df->s_file = s_file;
- df->numparms = f->def->type->num_parms;
- df->locals = locals_end - locals_start;
- df->parm_start = locals_start;
- for (i = 0; i < df->numparms; i++)
- df->parm_size[i] = type_size[f->def->type->parm_types[i]->type];
-
- continue;
- }
- else if (pr_immediate_type != type)
- PR_ParseError("wrong immediate type for %s", name);
-
- def->initialized = 1;
- memcpy(pr_globals + def->ofs, &pr_immediate, 4 * type_size[pr_immediate_type->type]);
- PR_Lex();
- }
-
- } while (PR_Check(","));
-
- PR_Expect(";");
- }
-
- /*
- * ============
- * PR_CompileFile
- *
- * compiles the 0 terminated text, adding defintions to the pr structure
- * ============
- */
- bool PR_CompileFile(register char *string, register char *filename)
- {
- if (!pr.memory) {
- eprintf("PR_CompileFile: Didn't clear");
- return FALSE;
- }
-
- PR_ClearGrabMacros(); /* clear the frame macros */
-
- pr_file_p = string;
- s_file = CopyString(filename);
-
- pr_source_line = 0;
-
- PR_NewLine();
-
- PR_Lex(); /* read first token */
-
- while (pr_token_type != tt_eof) {
- if (setjmp(pr_parse_abort)) {
- if (++pr_error_count > MAX_ERRORS)
- return FALSE;
- PR_SkipToSemicolon();
- if (pr_token_type == tt_eof)
- return FALSE;
- }
-
- pr_scope = NULL; /* outside all functions */
-
- PR_ParseDefs();
- }
-
- return (pr_error_count == 0);
- }
- /*
- * ===============
- * PR_String
- *
- * Returns a string suitable for printing (no newlines, max 60 chars length)
- * ===============
- */
- char *PR_String(register char *string)
- {
- static char buf[80];
- char *s;
-
- s = buf;
- *s++ = '"';
- while (string && *string) {
- if (s == buf + sizeof(buf) - 2)
- break;
- if (*string == '\n') {
- *s++ = '\\';
- *s++ = 'n';
- }
- else if (*string == '"') {
- *s++ = '\\';
- *s++ = '"';
- }
- else
- *s++ = *string;
- string++;
- if (s - buf > 60) {
- *s++ = '.';
- *s++ = '.';
- *s++ = '.';
- break;
- }
- }
- *s++ = '"';
- *s++ = 0;
- return buf;
- }
-
- def_t *PR_DefForFieldOfs(register gofs_t ofs)
- {
- def_t *d;
-
- for (d = pr.def_head; d; d = d->next) {
- if (d->type->type != ev_field)
- continue;
- if (*((int *)&pr_globals[d->ofs]) == ofs)
- return d;
- }
- eprintf("PR_DefForFieldOfs: couldn't find %i", ofs);
- return NULL;
- }
-
- /*
- * ============
- * PR_ValueString
- *
- * Returns a string describing *data in a type specific manner
- * =============
- */
- char *PR_ValueString(register etype_t type, register void *val)
- {
- static char line[256];
- def_t *def;
- dfunction_t *f;
-
- switch (type) {
- case ev_string:
- sprintf(line, "%s", PR_String(strings + *(int *)val));
- break;
- case ev_entity:
- sprintf(line, "entity %i", *(int *)val);
- break;
- case ev_function:
- f = functions + *(int *)val;
- if (!f)
- sprintf(line, "undefined function");
- else
- sprintf(line, "%s()", strings + f->s_name);
- break;
- case ev_field:
- def = PR_DefForFieldOfs(*(int *)val);
- sprintf(line, ".%s", def->name);
- break;
- case ev_void:
- sprintf(line, "void");
- break;
- case ev_float:
- sprintf(line, "%g", *(float *)val);
- break;
- case ev_vector:
- sprintf(line, "'%g %g %g'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
- break;
- case ev_pointer:
- sprintf(line, "pointer");
- break;
- default:
- sprintf(line, "bad type %i", type);
- break;
- }
-
- return line;
- }
-
- /*
- * ============
- * PR_GlobalString
- *
- * Returns a string with a description and the contents of a global,
- * padded to 20 field width
- * ============
- */
- char *PR_GlobalStringNoContents(register gofs_t ofs)
- {
- int i;
- def_t *def;
-
- /*void *val; */
- static char line[128];
-
- /*val = (void *)&pr_globals[ofs]; */
- def = pr_global_defs[ofs];
- if (!def)
- /* Error ("PR_GlobalString: no def for %i", ofs); */
- sprintf(line, "%i(???)", ofs);
- else
- sprintf(line, "%i(%s)", ofs, def->name);
-
- i = __strlen(line);
- for (; i < 16; i++)
- __strcat(line, " ");
- __strcat(line, " ");
-
- return line;
- }
-
- char *PR_GlobalString(register gofs_t ofs)
- {
- char *s;
- int i;
- def_t *def;
-
- /*void *val; */
- static char line[128];
-
- /*val = (void *)&pr_globals[ofs]; */
- def = pr_global_defs[ofs];
- if (!def)
- return PR_GlobalStringNoContents(ofs);
- if (def->initialized && def->type->type != ev_function) {
- s = PR_ValueString(def->type->type, &pr_globals[ofs]);
- sprintf(line, "%i(%s)", ofs, s);
- }
- else
- sprintf(line, "%i(%s)", ofs, def->name);
-
- i = __strlen(line);
- for (; i < 16; i++)
- __strcat(line, " ");
- __strcat(line, " ");
-
- return line;
- }
-
- /*
- * ============
- * PR_PrintOfs
- * ============
- */
- void PR_PrintOfs(register gofs_t ofs)
- {
- mprintf("%s\n", PR_GlobalString(ofs));
- }
-
- /*
- * =================
- * PR_PrintStatement
- * =================
- */
- void PR_PrintStatement(register dstatement_t * s)
- {
- int i;
-
- mprintf("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s - statements], pr_opcodes[s->op].opname);
- i = __strlen(pr_opcodes[s->op].opname);
- for (; i < 10; i++)
- mprintf(" ");
-
- if (s->op == OP_IF || s->op == OP_IFNOT)
- mprintf("%sbranch %i", PR_GlobalString(s->a), s->b);
- else if (s->op == OP_GOTO) {
- mprintf("branch %i", s->a);
- }
- else if ((unsigned)(s->op - OP_STORE_F) < 6) {
- mprintf("%s", PR_GlobalString(s->a));
- mprintf("%s", PR_GlobalStringNoContents(s->b));
- }
- else {
- if (s->a)
- mprintf("%s", PR_GlobalString(s->a));
- if (s->b)
- mprintf("%s", PR_GlobalString(s->b));
- if (s->c)
- mprintf("%s", PR_GlobalStringNoContents(s->c));
- }
- mprintf("\n");
- }
-
- /*
- * ============
- * PR_PrintDefs
- * ============
- */
- void PR_PrintDefs(void)
- {
- def_t *d;
-
- for (d = pr.def_head; d; d = d->next)
- PR_PrintOfs(d->ofs);
- }
-
- /*
- * ==============
- * PR_BeginCompilation
- *
- * called before compiling a batch of files, clears the pr struct
- * ==============
- */
- void PR_BeginCompilation(register void *memory, register int memsize)
- {
- int i;
-
- pr.memory = memory;
- pr.max_memory = memsize;
-
- numpr_globals = RESERVED_OFS;
- pr.def_tail = NULL;
-
- for (i = 0; i < RESERVED_OFS; i++)
- pr_global_defs[i] = &def_void;
-
- /* link the function type in so state forward declarations match proper type */
- pr.types = &type_function;
- type_function.next = NULL;
- pr_error_count = 0;
- }
-
- /*
- * ==============
- * PR_FinishCompilation
- *
- * called after all files are compiled to check for errors
- * Returns FALSE if errors were detected.
- * ==============
- */
- bool PR_FinishCompilation(void)
- {
- def_t *d;
- bool errors;
-
- errors = FALSE;
-
- /* check to make sure all functions prototyped have code */
- for (d = pr.def_head; d; d = d->next) {
- /* function parms are ok */
- if (d->type->type == ev_function && !d->scope) {
- /* f = G_FUNCTION(d->ofs); */
- /* if (!f || (!f->code && !f->builtin) ) */
- if (!d->initialized) {
- eprintf("function %s was not defined\n", d->name);
- errors = TRUE;
- }
- }
- }
-
- return !errors;
- }
-
- /*============================================================================= */
-
- /*
- * ============
- * PR_WriteProgdefs
- *
- * Writes the global and entity structures out
- * Returns a crc of the header, to be stored in the progs file for comparison
- * at load time.
- * ============
- */
- int PR_WriteProgdefs(register char *filename)
- {
- def_t *d;
- FILE *f;
- unsigned short int crc;
- int c;
-
- mprintf("writing %s\n", filename);
- f = fopen(filename, "w");
-
- /* print global vars until the first field is defined */
- fprintf(f, "\n/* file generated by qcc, do not modify */\n\ntypedef struct\n{\tint\tpad[%i];\n", RESERVED_OFS);
- for (d = pr.def_head; d; d = d->next) {
- if (!__strcmp(d->name, "end_sys_globals"))
- break;
-
- switch (d->type->type) {
- case ev_float:
- fprintf(f, "\tfloat\t%s;\n", d->name);
- break;
- case ev_vector:
- fprintf(f, "\tvec3_t\t%s;\n", d->name);
- d = d->next->next->next; /* skip the elements */
-
- break;
- case ev_string:
- fprintf(f, "\tstring_t\t%s;\n", d->name);
- break;
- case ev_function:
- fprintf(f, "\tfunc_t\t%s;\n", d->name);
- break;
- case ev_entity:
- fprintf(f, "\tint\t%s;\n", d->name);
- break;
- default:
- fprintf(f, "\tint\t%s;\n", d->name);
- break;
- }
- }
- fprintf(f, "} globalvars_t;\n\n");
-
- /* print all fields */
- fprintf(f, "typedef struct\n{\n");
- for (d = pr.def_head; d; d = d->next) {
- if (!__strcmp(d->name, "end_sys_fields"))
- break;
-
- if (d->type->type != ev_field)
- continue;
-
- switch (d->type->aux_type->type) {
- case ev_float:
- fprintf(f, "\tfloat\t%s;\n", d->name);
- break;
- case ev_vector:
- fprintf(f, "\tvec3_t\t%s;\n", d->name);
- d = d->next->next->next; /* skip the elements */
-
- break;
- case ev_string:
- fprintf(f, "\tstring_t\t%s;\n", d->name);
- break;
- case ev_function:
- fprintf(f, "\tfunc_t\t%s;\n", d->name);
- break;
- case ev_entity:
- fprintf(f, "\tint\t%s;\n", d->name);
- break;
- default:
- fprintf(f, "\tint\t%s;\n", d->name);
- break;
- }
- }
- fprintf(f, "} entvars_t;\n\n");
-
- fclose(f);
-
- /* do a crc of the file */
- CRC_Init(&crc);
- f = fopen(filename, "r+");
- while ((c = fgetc(f)) != EOF)
- CRC_ProcessByte(&crc, (unsigned char)c);
-
- fprintf(f, "#define PROGHEADER_CRC %i\n", crc);
- fclose(f);
-
- return crc;
- }
-
- void PrintFunction(register char *name)
- {
- int i;
- dstatement_t *ds;
- dfunction_t *df;
-
- for (i = 0; i < numfunctions; i++)
- if (!__strcmp(name, strings + functions[i].s_name))
- break;
- if (i == numfunctions)
- eprintf("No function names \"%s\"", name);
- else {
- df = functions + i;
-
- mprintf("Statements for %s:\n", name);
- ds = statements + df->first_statement;
- while (1) {
- PR_PrintStatement(ds);
- if (!ds->op)
- break;
- ds++;
- }
- }
- }
-
- /*============================================================================ */
-
- char com_token[1024];
- bool com_eof;
-
- /*
- * ==============
- * COM_Parse
- *
- * Parse a token out of a string
- * ==============
- */
- char *COM_Parse(register char *data)
- {
- int c;
- int len;
-
- len = 0;
- com_token[0] = 0;
-
- if (!data)
- return NULL;
-
- /* skip whitespace */
- skipwhite:
- while ((c = *data) <= ' ') {
- if (c == 0) {
- com_eof = TRUE;
- return NULL; /* end of file; */
-
- }
- data++;
- }
-
- /* skip // comments */
- if (c == '/' && data[1] == '/') {
- while (*data && *data != '\n')
- data++;
- goto skipwhite;
- }
-
- /* handle quoted strings specially */
- if (c == '\"') {
- data++;
- do {
- c = *data++;
- if (c == '\"') {
- com_token[len] = 0;
- return data;
- }
- com_token[len] = c;
- len++;
- } while (1);
- }
-
- /* parse single characters */
- if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':') {
- com_token[len] = c;
- len++;
- com_token[len] = 0;
- return data + 1;
- }
-
- /* parse a regular word */
- do {
- com_token[len] = c;
- data++;
- len++;
- c = *data;
- if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':')
- break;
- } while (c > 32);
-
- com_token[len] = 0;
- return data;
- }
-
- /*=========================================================================== */
- /*unqcc */
- /*=========================================================================== */
-
- FILE *DEC_ofile;
- FILE *DEC_progssrc;
-
- #ifdef QC_PROFILE
- FILE *DEC_profile;
-
- #endif
- char *DEC_FilesSeen[1024];
- int DEC_FileCtr = 0;
- char *DEC_Profiles[MAX_FUNCTIONS];
-
- char *type_names[8] =
- {"void", "string", "float", "vector", "entity", "ev_field", "void()", "ev_pointer"};
-
- char *builtins[79] =
- {
- NULL,
- "void (vector ang)",
- "void (entity e, vector o)",
- "void (entity e, string m)",
- "void (entity e, vector min, vector max)",
- NULL,
- "void ()",
- "float ()",
- "void (entity e, float chan, string samp, float vol, float atten)",
- "vector (vector v)",
- "void (string e)",
- "void (string e)",
- "float (vector v)",
- "float (vector v)",
- "entity ()",
- "void (entity e)",
- "void (vector v1, vector v2, float nomonsters, entity forent)",
- "entity ()",
- "entity (entity start, .string fld, string match)",
- "string (string s)",
- "string (string s)",
- "void (entity client, string s)",
- "entity (vector org, float rad)",
- "void (string s)",
- "void (entity client, string s)",
- "void (string s)",
- "string (float f)",
- "string (vector v)",
- "void ()",
- "void ()",
- "void ()",
- "void (entity e)",
- "float (float yaw, float dist)",
- NULL,
- "float (float yaw, float dist)",
- "void (float style, string value)",
- "float (float v)",
- "float (float v)",
- "float (float v)",
- NULL,
- "float (entity e)",
- "float (vector v)",
- NULL,
- "float (float f)",
- "vector (entity e, float speed)",
- "float (string s)",
- "void (string s)",
- "entity (entity e)",
- "void (vector o, vector d, float color, float count)",
- "void ()",
- NULL,
- "vector (vector v)",
- "void (float to, float f)",
- "void (float to, float f)",
- "void (float to, float f)",
- "void (float to, float f)",
- "void (float to, float f)",
- "void (float to, float f)",
- "void (float to, string s)",
- "void (float to, entity s)",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "void (float step)",
- "string (string s)",
- "void (entity e)",
- "void (string s)",
- NULL,
- "void (string var, string val)",
- "void (entity client, string s)",
- "void (vector pos, string samp, float vol, float atten)",
- "string (string s)",
- "string (string s)",
- "string (string s)",
- "void (entity e)"
- };
-
- int DEC_GetFunctionIdxByName(register char *name)
- {
- int i;
-
- for (i = 1; i < numfunctions; i++)
- if (!__strcmp(name, strings + functions[i].s_name)) {
- break;
- }
- return i;
- }
-
- int DEC_AlreadySeen(register char *fname)
- {
- int i;
- char *new;
-
- if (DEC_FileCtr > 1000)
- eprintf("DEC_AlreadySeen - too many source files.");
- else {
- for (i = 0; i < DEC_FileCtr; i++) {
- if (!__strcmp(fname, DEC_FilesSeen[i]))
- return 1;
- }
-
- /*new = (char *)kmalloc(__strlen(fname) + 1); */
- /*__strcpy(new, fname); */
- new = smalloc(fname);
- DEC_FilesSeen[DEC_FileCtr] = new;
- DEC_FileCtr++;
-
- mprintf("decompiling %s\n", fname);
- }
- return 0;
- }
-
- ddef_t *DEC_GetParameter(register gofs_t ofs)
- {
- int i;
- ddef_t *def;
-
- def = NULL;
-
- for (i = 0; i < numglobaldefs; i++) {
- def = &globals[i];
-
- if (def->ofs == ofs) {
- return def;
- }
- }
-
- return NULL;
- }
-
- /*
- * fix: same as PR_String
- */
- char *DEC_String(register char *string)
- {
- static char buf[255];
- char *s;
- int c = 1;
-
- s = buf;
- *s++ = '"';
- while (string && *string) {
- if (c == sizeof(buf) - 2)
- break;
- if (*string == '\n') {
- *s++ = '\\';
- *s++ = 'n';
- c++;
- }
- else if (*string == '"') {
- *s++ = '\\';
- *s++ = '"';
- c++;
- }
- else {
- *s++ = *string;
- c++;
- }
- string++;
- if (c > sizeof(buf) - 10) {
- *s++ = '.';
- *s++ = '.';
- *s++ = '.';
- c += 3;
- break;
- }
- }
- *s++ = '"';
- *s++ = 0;
- return buf;
- }
-
- /*
- * fix: same as PR_ValueString
- */
- char *DEC_ValueString(register etype_t type, register void *val)
- {
- static char line[1024];
-
- line[0] = '\0';
-
- switch (type) {
- case ev_string:
- sprintf(line, "%s", DEC_String(strings + *(int *)val));
- break;
- case ev_void:
- sprintf(line, "void");
- break;
- case ev_float:
- sprintf(line, "%g", *(float *)val);
- break;
- case ev_vector:
- sprintf(line, "'%g %g %g'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
- break;
- default:
- sprintf(line, "bad type %i", type);
- break;
- }
-
- return line;
- }
-
- char *DEC_PrintParameter(register ddef_t * def)
- {
- static char line[128];
-
- line[0] = '0';
-
- if (!__strcmp(strings + def->s_name, "IMMEDIATE")) {
- sprintf(line, "%s", DEC_ValueString(def->type, &pr_globals[def->ofs]));
- }
- else
- sprintf(line, "%s %s", type_names[def->type], strings + def->s_name);
-
- return line;
- }
-
- void DEC_CalcProfiles(void)
- {
- int i, j, ps;
- static char fname[512];
- static char line[512];
- char *new;
- dfunction_t *df;
- dstatement_t *ds, *rds;
- ddef_t *par;
- unsigned short dom;
-
- for (i = 1; i < numfunctions; i++) {
- df = functions + i;
- fname[0] = '\0';
- line[0] = '\0';
- DEC_Profiles[i] = NULL;
-
- if (df->first_statement <= 0) {
- sprintf(fname, "%s %s", builtins[-df->first_statement], strings + functions[i].s_name);
- }
- else {
- ds = statements + df->first_statement;
- rds = NULL;
-
- /* find a return statement, to determine the result type */
-
- while (1) {
- dom = (ds->op) % 100;
- if (!dom)
- break;
- if (dom == OP_RETURN) {
- rds = ds;
- /* break; */
- }
- ds++;
- }
-
- /* print the return type */
- if ((rds != NULL) && (rds->a != 0)) {
- par = DEC_GetParameter(rds->a);
-
- if (par) {
- sprintf(fname, "%s ", type_names[par->type]);
- }
- else {
- sprintf(fname, "float /* ERROR: Could not determine return type */ ");
- }
- }
- else {
- sprintf(fname, "\nvoid ");
- }
- __strcat(fname, "(");
-
- /* determine overall parameter size */
-
- for (j = 0, ps = 0; j < df->numparms; j++)
- ps += df->parm_size[j];
-
- if (ps > 0) {
- for (j = df->parm_start; j < (df->parm_start) + ps; j++) {
- line[0] = '\0';
- par = DEC_GetParameter(j);
-
- if (!par)
- eprintf("DEC_CalcProfiles - No parameter names with offset %i.", j);
- else {
- if (par->type == ev_vector)
- j += 2;
-
- if (j < (df->parm_start) + ps - 1) {
- sprintf(line, "%s, ", DEC_PrintParameter(par));
- }
- else {
- sprintf(line, "%s", DEC_PrintParameter(par));
- }
- __strcat(fname, line);
- }
- }
- }
- __strcat(fname, ") ");
- line[0] = '\0';
- sprintf(line, strings + functions[i].s_name);
- __strcat(fname, line);
- }
-
- if (i >= MAX_FUNCTIONS)
- eprintf("DEC_CalcProfiles - too many functions.");
- else {
- /*new = (char *)kmalloc(__strlen(fname) + 1); */
- /*__strcpy(new, fname); */
- new = smalloc(fname);
- DEC_Profiles[i] = new;
- }
- }
- }
-
- char *DEC_Global(register gofs_t ofs, register def_t * req_t)
- {
- int i;
- ddef_t *def;
- static char line[256];
- char *res;
- char found = 0;
-
- line[0] = '\0';
-
- def = NULL;
-
- for (i = 0; i < numglobaldefs; i++) {
- def = &globals[i];
- if (def->ofs == ofs) {
- oprintf("DEC_Global - Found %i at %i.\n", ofs, (int)def);
- found = 1;
- break;
- }
- }
-
- if (found) {
- if (!__strcmp(strings + def->s_name, "IMMEDIATE"))
- sprintf(line, "%s", DEC_ValueString(def->type, &pr_globals[def->ofs]));
- else {
-
- sprintf(line, "%s", strings + def->s_name);
- if (def->type == ev_vector && req_t == &def_float)
- __strcat(line, "_x");
- }
- /*res = (char *)kmalloc(__strlen(line) + 1); */
- /*__strcpy(res, line); */
- res = smalloc(line);
-
- oprintf("DEC_Global - Found \"%s\"(%i) at %i.\n", line, ofs, (int)def);
- return res;
-
- }
- return NULL;
- }
-
- gofs_t DEC_ScaleIndex(register dfunction_t * df, register gofs_t ofs)
- {
- gofs_t nofs = 0;
-
- if (ofs > RESERVED_OFS)
- nofs = ofs - df->parm_start + RESERVED_OFS;
- else
- nofs = ofs;
-
- return nofs;
- }
-
- #define MAX_NO_LOCAL_IMMEDIATES 1024
-
- char *DEC_Immediate(register dfunction_t * df, register gofs_t ofs, register int fun, register char *new)
- {
- int i;
- gofs_t nofs;
- static char *IMMEDIATES[MAX_NO_LOCAL_IMMEDIATES];
-
- /*
- * free 'em all
- */
- if (fun == 0) {
- oprintf("DEC_Immediate - Initializing function environment.\n");
- for (i = 0; i < MAX_NO_LOCAL_IMMEDIATES; i++)
- if (IMMEDIATES[i])
- tfree(IMMEDIATES[i]);
- bzero(&IMMEDIATES, MAX_NO_LOCAL_IMMEDIATES * sizeof(char *));
-
- return NULL;
- }
-
- nofs = DEC_ScaleIndex(df, ofs);
- oprintf("DEC_Immediate - Index scale: %i -> %i.\n", ofs, nofs);
-
- /*
- * check consistency
- */
- if ((nofs <= 0) || (nofs > MAX_NO_LOCAL_IMMEDIATES - 1))
- eprintf("DEC_Immediate - Index (%i) out of bounds.\n", nofs);
- else {
- /*
- * insert at nofs
- */
- if (fun == 1) {
- if (IMMEDIATES[nofs])
- tfree(IMMEDIATES[nofs]);
- IMMEDIATES[nofs] = smalloc(new);
- oprintf("DEC_Immediate - Putting \"%s\" at index %i.\n", new, nofs);
- }
-
- /*
- * get from nofs
- */
- if (fun == 2) {
- if (IMMEDIATES[nofs]) {
- oprintf("DEC_Immediate - Reading \"%s\" at index %i.\n", IMMEDIATES[nofs], nofs);
- return smalloc(IMMEDIATES[nofs]);
- }
- else
- eprintf("DEC_Immediate - %i not defined.", nofs);
- }
- }
-
- return NULL;
- }
-
- char *DEC_Get(register dfunction_t * df, register gofs_t ofs, register def_t * req_t)
- {
- char *arg1 = NULL;
-
- arg1 = DEC_Global(ofs, req_t);
-
- if (arg1 == NULL)
- arg1 = DEC_Immediate(df, ofs, 2, NULL);
-
- /*
- * if (arg1)
- * mprintf("DEC_Get - found \"%s\".\n",arg1);
- */
-
- return arg1;
- }
-
- void DEC_Indent(register int c)
- {
- int i;
-
- if (c < 0)
- c = 0;
-
- for (i = 0; i < c; i++) {
- fprintf(DEC_ofile, " ");
- }
- }
-
- void DEC_DecompileStatement(register dfunction_t * df, register dstatement_t * s, register int *indent)
- {
- static char line[512];
- static char fnam[512];
- char *arg1, *arg2, *arg3;
- int nargs, i, j;
- dstatement_t *t;
- unsigned short dom, doc, ifc, tom;
- def_t *typ1, *typ2, *typ3;
-
- dstatement_t *k;
- int dum;
-
- arg1 = arg2 = arg3 = NULL;
-
- line[0] = '\0';
- fnam[0] = '\0';
-
- dom = s->op;
-
- doc = dom / 10000;
- ifc = (dom % 10000) / 100;
-
- /*
- * use program flow information
- */
- for (i = 0; i < ifc; i++) {
- (*indent)--;
- fprintf(DEC_ofile, "\n");
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "}\n");
- }
- for (i = 0; i < doc; i++) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "do {\n\n");
- (*indent)++;
- }
-
- /*
- * remove all program flow information
- */
- s->op %= 100;
-
- typ1 = pr_opcodes[s->op].type_a;
- typ2 = pr_opcodes[s->op].type_b;
- typ3 = pr_opcodes[s->op].type_c;
-
- /*
- * mprintf("DEC_DecompileStatement - decompiling %i (%i):\n",(int)(s - statements),dom);
- * DEC_PrintStatement (s);
- */
- /* states are handled at top level */
- if (s->op == OP_DONE || s->op == OP_STATE) {
- }
- else if (s->op == OP_RETURN) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "return ");
-
- if (s->a) {
- arg1 = DEC_Get(df, s->a, typ1);
- fprintf(DEC_ofile, "( %s )", arg1);
- }
-
- fprintf(DEC_ofile, ";\n");
- }
- else if ((OP_MUL_F <= s->op && s->op <= OP_SUB_V) ||
- (OP_EQ_F <= s->op && s->op <= OP_GT) ||
- (OP_AND <= s->op && s->op <= OP_BITOR)) {
- arg1 = DEC_Get(df, s->a, typ1);
- arg2 = DEC_Get(df, s->b, typ2);
- arg3 = DEC_Global(s->c, typ3);
-
- if (arg3) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "%s = %s %s %s;\n", arg3, arg1, pr_opcodes[s->op].name, arg2);
- }
- else {
- sprintf(line, "(%s %s %s)", arg1, pr_opcodes[s->op].name, arg2);
- DEC_Immediate(df, s->c, 1, line);
- }
- }
- else if (OP_LOAD_F <= s->op && s->op <= OP_ADDRESS) {
- arg1 = DEC_Get(df, s->a, typ1);
- arg2 = DEC_Get(df, s->b, typ2);
- arg3 = DEC_Global(s->c, typ3);
-
- if (arg3) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "%s = %s.%s;\n", arg3, arg1, arg2);
- }
- else {
- sprintf(line, "%s.%s", arg1, arg2);
- DEC_Immediate(df, s->c, 1, line);
- }
- }
- else if (OP_STORE_F <= s->op && s->op <= OP_STORE_FNC) {
- arg1 = DEC_Get(df, s->a, typ1);
- arg3 = DEC_Global(s->b, typ2);
-
- if (arg3) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "%s = %s;\n", arg3, arg1);
- }
- else {
- sprintf(line, "%s", arg1);
- DEC_Immediate(df, s->b, 1, line);
- }
- }
- else if (OP_STOREP_F <= s->op && s->op <= OP_STOREP_FNC) {
- arg1 = DEC_Get(df, s->a, typ1);
- arg2 = DEC_Get(df, s->b, typ2);
-
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "%s = %s;\n", arg2, arg1);
- }
- else if (OP_NOT_F <= s->op && s->op <= OP_NOT_FNC) {
- arg1 = DEC_Get(df, s->a, typ1);
- sprintf(line, "!%s", arg1);
- DEC_Immediate(df, s->c, 1, line);
- }
- else if (OP_CALL0 <= s->op && s->op <= OP_CALL8) {
- nargs = s->op - OP_CALL0;
- arg1 = DEC_Get(df, s->a, NULL);
- sprintf(line, "%s (", arg1);
- sprintf(fnam, "%s", arg1);
-
- for (i = 0; i < nargs; i++) {
- typ1 = NULL;
- j = 4 + 3 * i;
-
- if (arg1) {
- tfree(arg1);
- arg1 = 0;
- }
-
- arg1 = DEC_Get(df, j, typ1);
- __strcat(line, arg1);
-
- #ifndef DONT_USE_DIRTY_TRICKS
- if (!__strcmp(fnam, "WriteCoord"))
- if (!__strcmp(arg1, "org") || !__strcmp(arg1, "trace_endpos") || !__strcmp(arg1, "p1") || !__strcmp(arg1, "p2") || !__strcmp(arg1, "o"))
- __strcat(line, "_x");
- #endif
- if (i < nargs - 1)
- __strcat(line, ",");
- }
- __strcat(line, ")");
- DEC_Immediate(df, 1, 1, line);
-
- /*
- * if ( ( ( (s+1)->a != 1) && ( (s+1)->b != 1) &&
- * ( (s+2)->a != 1) && ( (s+2)->b != 1) ) ||
- * ( ((s+1)->op) % 100 == OP_CALL0 ) ) {
- * DEC_Indent(*indent);
- * fprintf(DEC_ofile,"%s;\n",line);
- * }
- */
- /* this SUCKS!!!!!!!!!!!!! */
- if ((((s + 1)->a != 1) && ((s + 1)->b != 1) &&
- ((s + 2)->a != 1) && ((s + 2)->b != 1)) ||
- ((((s + 1)->op) % 100 == OP_CALL0) && ((((s + 2)->a != 1)) || ((s + 2)->b != 1)))) {
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "%s;\n", line);
- }
- }
- else if (s->op == OP_IF || s->op == OP_IFNOT) {
- arg1 = DEC_Get(df, s->a, NULL);
- arg2 = DEC_Global(s->a, NULL);
-
- if (s->op == OP_IFNOT) {
- if (s->b < 1) {
- eprintf("Found a negative IFNOT jump.");
- return;
- }
-
- /* get instruction right before the target */
- t = s + s->b - 1;
- tom = t->op % 100;
-
- if (tom != OP_GOTO) {
- /* pure if */
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "if ( %s ) {\n\n", arg1);
- (*indent)++;
- }
- else {
- if (t->a > 0) {
- /* ite */
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "if ( %s ) {\n\n", arg1);
- (*indent)++;
- }
- else {
- if ((t->a + s->b) > 1) {
- /* pure if */
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "if ( %s ) {\n\n", arg1);
- (*indent)++;
- }
- else {
- dum = 1;
- for (k = t + (t->a); k < s; k++) {
- tom = k->op % 100;
- if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
- dum = 0;
- }
- if (dum) {
- /* while */
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "while ( %s ) {\n\n", arg1);
- (*indent)++;
- }
- else {
- /* pure if */
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "if ( %s ) {\n\n", arg1);
- (*indent)++;
- }
- }
- }
- }
- }
- else {
- /* do ... while */
- (*indent)--;
- fprintf(DEC_ofile, "\n");
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "} while ( %s );\n", arg1);
- }
- }
- else if (s->op == OP_GOTO) {
- if (s->a > 0) {
- /* else */
- (*indent)--;
- fprintf(DEC_ofile, "\n");
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "} else {\n\n");
- (*indent)++;
- }
- else {
- /* while */
- (*indent)--;
- fprintf(DEC_ofile, "\n");
- DEC_Indent(*indent);
- fprintf(DEC_ofile, "}\n");
- }
- }
- else {
- fprintf(DEC_ofile, "\n/* ERROR: UNKNOWN COMMAND */\n");
- }
-
- oprintf("DEC_DecompileStatement - Current line is \"%s\"\n", line);
- if (arg1) {
- tfree(arg1);
- arg1 = 0;
- }
- if (arg2) {
- tfree(arg2);
- arg2 = 0;
- }
- if (arg3) {
- tfree(arg3);
- arg3 = 0;
- }
-
- return;
- }
-
- void DEC_DecompileFunction(register dfunction_t * df)
- {
- dstatement_t *ds;
- int indent;
-
- /* Initialize */
- DEC_Immediate(df, 0, 0, NULL);
-
- indent = 1;
-
- ds = statements + df->first_statement;
- while (1) {
- DEC_DecompileStatement(df, ds, &indent);
- if (!ds->op)
- break;
- ds++;
- }
-
- if (indent != 1)
- fprintf(DEC_ofile, "/* ERROR : Indentiation structure corrupt */\n");
- }
-
- ddef_t *GetField(register char *name)
- {
- int i;
- ddef_t *d;
-
- for (i = 1; i < numfielddefs; i++) {
- d = &fields[i];
-
- if (!__strcmp(strings + d->s_name, name))
- return d;
- }
- return NULL;
- }
-
- void DEC_Function(register char *name)
- {
- int i, findex, ps;
- dstatement_t *ds, *ts;
- dfunction_t *df;
- ddef_t *par;
- char *arg2;
- unsigned short dom, tom;
-
- int j, start, end;
- dfunction_t *dfpred;
- ddef_t *ef;
-
- static char line[256];
-
- dstatement_t *k;
- int dum;
-
- for (i = 1; i < numfunctions; i++)
- if (!__strcmp(name, strings + functions[i].s_name))
- break;
- if (i == numfunctions) {
- eprintf("No function named \"%s\"", name);
- return;
- }
-
- df = functions + i;
-
- findex = i;
-
- /* Check ''local globals'' */
- dfpred = df - 1;
-
- for (j = 0, ps = 0; j < dfpred->numparms; j++)
- ps += dfpred->parm_size[j];
-
- start = dfpred->parm_start + dfpred->locals + ps;
-
- if (dfpred->first_statement < 0 && df->first_statement > 0)
- start -= 1;
-
- if (start == 0)
- start = 1;
-
- end = df->parm_start;
-
- for (j = start; j < end; j++) {
- par = DEC_GetParameter(j);
-
- if (par) {
- if (par->type & (1 << 15))
- par->type -= (1 << 15);
-
- if (par->type == ev_function) {
- if (__strcmp(strings + par->s_name, "IMMEDIATE"))
- if (__strcmp(strings + par->s_name, name)) {
- fprintf(DEC_ofile, "%s;\n", DEC_Profiles[DEC_GetFunctionIdxByName(strings + par->s_name)]);
- }
- }
- else if (par->type != ev_pointer)
- if (__strcmp(strings + par->s_name, "IMMEDIATE")) {
- if (par->type == ev_field) {
- ef = GetField(strings + par->s_name);
-
- if (!ef) {
- eprintf("Could not locate a field named \"%s\"", strings + par->s_name);
- return;
- }
-
- if (ef->type == ev_vector)
- j += 3;
- #ifndef DONT_USE_DIRTY_TRICKS
- if ((ef->type == ev_function) && !__strcmp(strings + ef->s_name, "th_pain")) {
- fprintf(DEC_ofile, ".void(entity attacker, float damage) th_pain;\n");
- }
- else
- #endif
- fprintf(DEC_ofile, ".%s %s;\n", type_names[ef->type], strings + ef->s_name);
- }
- else {
- if (par->type == ev_vector)
- j += 2;
- if (par->type == ev_entity || par->type == ev_void) {
- fprintf(DEC_ofile, "%s %s;\n", type_names[par->type], strings + par->s_name);
- }
- else {
- line[0] = '\0';
- sprintf(line, "%s", DEC_ValueString(par->type, &pr_globals[par->ofs]));
-
- if ((__strlen(strings + par->s_name) > 1) &&
- isupper((strings + par->s_name)[0]) &&
- (isupper((strings + par->s_name)[1]) || (strings + par->s_name)[1] == '_')) {
- fprintf(DEC_ofile, "%s %s = %s;\n", type_names[par->type], strings + par->s_name, line);
- }
- else
- fprintf(DEC_ofile, "%s %s /* = %s */;\n", type_names[par->type], strings + par->s_name, line);
- }
- }
- }
- }
- }
- /* Check ''local globals'' */
- if (df->first_statement <= 0) {
- fprintf(DEC_ofile, "%s", DEC_Profiles[findex]);
- fprintf(DEC_ofile, " = #%i; \n", -df->first_statement);
- return;
- }
-
- ds = statements + df->first_statement;
-
- while (1) {
- dom = (ds->op) % 100;
-
- if (!dom)
- break;
- else if (dom == OP_GOTO) {
- /*
- * check for i-t-e
- */
- if (ds->a > 0) {
- ts = ds + ds->a;
- /* mark the end of a if/ite construct */
- ts->op += 100;
- }
- }
- else if (dom == OP_IFNOT) {
- /*
- * check for pure if
- */
- ts = ds + ds->b;
- tom = (ts - 1)->op % 100;
-
- if (tom != OP_GOTO)
- /* mark the end of a if/ite construct */
- ts->op += 100;
- else if ((ts - 1)->a < 0) {
- /*
- * arg2 = DEC_Global(ds->a,NULL);
- *
- * if (!( ( ((ts-1)->a + ds->b) == 0) ||
- * ( (arg2 != NULL) && (((ts-1)->a + ds->b) == 1) )))
- * (ts-1)->op += 100;
- *
- * if (arg2) {
- * tfree(arg2);
- * arg2 = 0;
- * }
- */
- if (((ts - 1)->a + ds->b) > 1) {
- /* pure if */
- /* mark the end of a if/ite construct */
- ts->op += 100;
- }
- else {
- dum = 1;
- for (k = (ts - 1) + ((ts - 1)->a); k < ds; k++) {
- tom = k->op % 100;
- if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
- dum = 0;
- }
- if (!dum) {
- /* pure if */
- /* mark the end of a if/ite construct */
- ts->op += 100;
- }
- }
- }
- }
- else if (dom == OP_IF) {
- ts = ds + ds->b;
- /* mark the start of a do construct */
- ts->op += 10000;
- }
- ds++;
- }
-
- /* print the prototype */
- fprintf(DEC_ofile, "%s", DEC_Profiles[findex]);
-
- /* handle state functions */
- ds = statements + df->first_statement;
-
- if (ds->op == OP_STATE) {
- par = DEC_GetParameter(ds->a);
- if (!par) {
- eprintf("DEC_Function - Can't determine frame number.");
- return;
- }
-
- arg2 = DEC_Get(df, ds->b, NULL);
- if (!arg2) {
- eprintf("DEC_Function - No state parameter with offset %i.", ds->b);
- return;
- }
-
- fprintf(DEC_ofile, " = [ %s, %s ]", DEC_ValueString(par->type, &pr_globals[par->ofs]), arg2);
- tfree(arg2);
- arg2 = 0;
- }
- else {
- fprintf(DEC_ofile, " =");
- }
- fprintf(DEC_ofile, " {\n\n");
-
- #ifdef QC_PROFILE
- fprintf(DEC_profile, "%s", DEC_Profiles[findex]);
- fprintf(DEC_profile, ") %s;\n", name);
- #endif
-
- /* calculate the parameter size */
- for (j = 0, ps = 0; j < df->numparms; j++)
- ps += df->parm_size[j];
-
- /* print the locals */
- if (df->locals > 0) {
- if ((df->parm_start) + df->locals - 1 >= (df->parm_start) + ps) {
- for (i = df->parm_start + ps; i < (df->parm_start) + df->locals; i++) {
- par = DEC_GetParameter(i);
-
- if (!par) {
- fprintf(DEC_ofile, " /* ERROR: No local name with offset %i */\n", i);
- }
- else {
- if (par->type == ev_function)
- fprintf(DEC_ofile, " /* ERROR: Fields and functions must be global */\n");
- else
- fprintf(DEC_ofile, " local %s;\n", DEC_PrintParameter(par));
- if (par->type == ev_vector)
- i += 2;
- }
- }
-
- fprintf(DEC_ofile, "\n");
- }
- }
-
- /* do the hard work */
- DEC_DecompileFunction(df);
- fprintf(DEC_ofile, "\n};\n");
- }
-
- bool DEC_DecompileFunctions(register char *destDir)
- {
- int i;
- dfunction_t *d;
- FILE *f;
- char fname[512];
-
- DEC_CalcProfiles();
-
- fname[0] = '\0';
- sprintf(fname, "%s%s", destDir, "progs.src");
- DEC_progssrc = fopen(fname, "w");
- if (!DEC_progssrc) {
- eprintf("DEC_DecompileFunctions - Could not open \"progs.src\" for output.");
- return FALSE;
- }
-
- fprintf(DEC_progssrc, "./progs.dat\n\n");
-
- #ifdef QC_PROFILE
- DEC_profile = fopen("!profile.qc", "w");
- if (!DEC_profile)
- Error("DEC_DecompileFunctions - Could not open \"!profile.qc\" for output.");
- fprintf(DEC_progssrc, "!profile.qc\n");
- #endif
-
- for (i = 1; i < numfunctions; i++) {
- d = &functions[i];
-
- fname[0] = '\0';
- sprintf(fname, "%s%s", destDir, strings + d->s_file);
- f = fopen(fname, "a+");
-
- if (!DEC_AlreadySeen(fname))
- fprintf(DEC_progssrc, "%s\n", fname);
-
- if (!f) {
- eprintf("DEC_DecompileFunctions - Could not open \"%s\" for output.", fname);
- return FALSE;
- }
- DEC_ofile = f;
- DEC_Function(strings + d->s_name);
-
- if (fclose(f)) {
- eprintf("DEC_DecompileFunctions - Could not close \"%s\" properly.", fname);
- return FALSE;
- }
- }
-
- if (fclose(DEC_progssrc)) {
- eprintf("DEC_DecompileFunctions - Could not close \"progs.src\" properly.");
- return FALSE;
- }
-
- #ifdef QC_PROFILE
- if (fclose(DEC_profile))
- Error("DEC_DecompileFunctions - Could not close \"!profile.qc\" properly.");
- #endif
- return TRUE;
- }
-
- char *DEC_GlobalStringNoContents(register gofs_t ofs)
- {
- int i;
- ddef_t *def;
- static char line[128];
-
- line[0] = '0';
- sprintf(line, "%i(???)", ofs);
-
- for (i = 0; i < numglobaldefs; i++) {
- def = &globals[i];
-
- if (def->ofs == ofs) {
- line[0] = '0';
- sprintf(line, "%i(%s)", def->ofs, strings + def->s_name);
- break;
- }
- }
-
- i = __strlen(line);
- for (; i < 16; i++)
- __strcat(line, " ");
- __strcat(line, " ");
-
- return line;
- }
-
- char *DEC_GlobalString(register gofs_t ofs)
- {
- char *s;
- int i;
- ddef_t *def;
- static char line[128];
-
- line[0] = '0';
- sprintf(line, "%i(???)", ofs);
-
- for (i = 0; i < numglobaldefs; i++) {
- def = &globals[i];
-
- if (def->ofs == ofs) {
-
- line[0] = '0';
- if (!__strcmp(strings + def->s_name, "IMMEDIATE")) {
- s = PR_ValueString(def->type, &pr_globals[ofs]);
- sprintf(line, "%i(%s)", def->ofs, s);
- }
- else
- sprintf(line, "%i(%s)", def->ofs, strings + def->s_name);
- }
- }
-
- i = __strlen(line);
- for (; i < 16; i++)
- __strcat(line, " ");
- __strcat(line, " ");
-
- return line;
- }
-
- /*
- * fix: same as PR_PrintStatement
- * mprintf("%4i : %4i : %s ", (int)(s - statements), statement_linenums[s - statements], pr_opcodes[s->op].opname);
- */
- void DEC_PrintStatement(register dstatement_t * s)
- {
- int i;
-
- mprintf("%4i : %s ", (int)(s - statements), pr_opcodes[s->op].opname);
- i = __strlen(pr_opcodes[s->op].opname);
- for (; i < 10; i++)
- mprintf(" ");
-
- if (s->op == OP_IF || s->op == OP_IFNOT)
- mprintf("%sbranch %i", DEC_GlobalString(s->a), s->b);
- else if (s->op == OP_GOTO) {
- mprintf("branch %i", s->a);
- }
- else if ((unsigned)(s->op - OP_STORE_F) < 6) {
- mprintf("%s", DEC_GlobalString(s->a));
- mprintf("%s", DEC_GlobalStringNoContents(s->b));
- }
- else {
- if (s->a)
- mprintf("%s", DEC_GlobalString(s->a));
- if (s->b)
- mprintf("%s", DEC_GlobalString(s->b));
- if (s->c)
- mprintf("%s", DEC_GlobalStringNoContents(s->c));
- }
- mprintf("\n");
- }
-
- /*
- * fix: same as PrintFunction
- */
- void DEC_PrintFunction(register char *name)
- {
- int i;
- dstatement_t *ds;
- dfunction_t *df;
-
- for (i = 0; i < numfunctions; i++)
- if (!__strcmp(name, strings + functions[i].s_name))
- break;
- if (i == numfunctions)
- eprintf("No function names \"%s\"", name);
- else {
- df = functions + i;
-
- mprintf("Statements for %s:\n", name);
- ds = statements + df->first_statement;
- while (1) {
- DEC_PrintStatement(ds);
-
- if (!ds->op)
- break;
-
- ds++;
- }
- }
- }
-
- /*=========================================================================== */
- /*interface */
- /*=========================================================================== */
-
- bool qcc(FILE * srcFile, char *srcDir, operation procOper)
- {
- char *srcData, *srcFree = 0;
- char *srcPart;
- char fileName[1024];
- void *freeIt = 0;
- bool failure = FALSE;
-
- if (InitData()) {
- switch (procOper) {
- case OP_ADD:
- __strcpy(sourcedir, srcDir);
- if (!(srcData = srcFree = (char *)GetVoidF(fileno(srcFile))))
- break;
-
- if (!(srcData = COM_Parse(srcData))) {
- eprintf("No destination fileName.\n");
- tfree(srcFree);
- srcFree = 0;
- break;
- }
-
- __strcpy(destfile, com_token);
- mprintf("outputfile: %s\n", destfile);
-
- pr_dumpasm = FALSE;
- PR_BeginCompilation(freeIt = (void *)kmalloc(0x100000), 0x100000);
-
- /* compile all the files */
- do {
- if (!(srcData = COM_Parse(srcData)))
- break;
-
- sprintf(fileName, "%s%s", sourcedir, com_token);
- mprintf("compiling %s\n", fileName);
- if (!(srcPart = (char *)GetPreProcessed(fileName))) {
- eprintf(failed_fileopen, fileName);
- failure = TRUE;
- break;
- }
-
- if (!PR_CompileFile(srcPart, fileName)) {
- eprintf("cannot compile %s\n", fileName);
- tfree(srcPart);
- srcPart = 0;
- failure = TRUE;
- break;
- }
- else {
- tfree(srcPart);
- srcPart = 0;
- }
- } while (1);
-
- if (!failure) {
- if (PR_FinishCompilation()) {
- /* write progdefs.h */
- sprintf(fileName, "%s%s", sourcedir, "progdefs.h");
- /* write data file */
- WriteData(PR_WriteProgdefs(fileName));
- /* write files.dat */
- WriteFiles();
- }
- else
- eprintf("compilation errors\n");
- }
- else
- eprintf("compilation errors\n");
-
- tfree(srcFree);
- srcFree = 0;
- break;
- default:
- break;
- }
- ExitData();
- return TRUE;
- }
- else
- return FALSE;
- }
-
- bool unqcc(HANDLE srcFile, char *destDir, operation procOper)
- {
- bool retval = FALSE;
-
- switch (procOper) {
- case OP_EXTRACT:
- if (ReadData(srcFile)) {
- CreatePath(destDir);
- retval = DEC_DecompileFunctions(destDir);
- }
- else
- eprintf("decompilation error!\n");
- break;
- case OP_LIST:
- default:
- retval = ShowData(srcFile);
- break;
- }
-
- ExitData();
- return retval;
- }
-